WebView使用詳解纵潦、H5網(wǎng)頁視頻全屏播放 徐鹤、網(wǎng)頁跳轉(zhuǎn)空白

image.png

內(nèi)容:介紹webview的使用方法,介紹WebViewClient邀层、WebChromeClient返敬,H5網(wǎng)頁視頻全屏播放,網(wǎng)頁跳轉(zhuǎn)空白問題
最近做項目老愛和H5打交道寥院,遇到了很多問題也踩了許多坑劲赠,今天在這兒總結(jié)下,方便后人乘涼秸谢。
關(guān)于安卓和H5交互可參考我之前的文章:原生與H5交互介紹
WebView基礎(chǔ)設(shè)置

private void initWebView() {
        mWebView.setWebViewClient(new MyWebViewClient());       //設(shè)置在WebView中打開鏈接凛澎,不設(shè)置則調(diào)用自帶瀏覽器。主要針對View進行攔截處理
        mWebView.setWebChromeClient(new MyWebChromeClient());

        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);     //支持JS
        webSettings.setDomStorageEnabled(true);       //啟用dom內(nèi)存估蹄,防止js加載失敗
        webSettings.setAllowFileAccess(true);       //允許訪問文件
        webSettings.setSupportZoom(true);       //支持縮放
        webSettings.setLoadWithOverviewMode(true);      //是否啟動概述模式瀏覽界面塑煎,當頁面寬度超過WebView顯示寬度時,縮小頁面適應(yīng)WebView臭蚁。默認false
        webSettings.setGeolocationEnabled(false);       //是否允許定位
        webSettings.setLoadsImagesAutomatically(true);      //是否加載圖片
//      webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);     //設(shè)置緩存模式
//      webSettings.setDefaultTextEncodingName("UTF-8");        //設(shè)置頁面的編碼格式最铁,默認UTF-8
    }

WebViewClient主要是對view一系列操作進行監(jiān)聽攔截。包括:網(wǎng)頁加載開始垮兑、網(wǎng)頁加載完成冷尉、錯誤攔截處理。(代碼中注釋會詳解系枪,再次不多做介紹)
WebChromeClient主要是對瀏覽器進行監(jiān)聽雀哨。例如彈窗、是否顯示支持全屏播放等嗤无。(代碼中注釋會詳解震束,再次不多做介紹)
網(wǎng)頁加載空白問題怜庸,我只在7.0及以上遇到,貌似是說證書錯誤垢村,可能越往上安全性越高吧割疾,按照下面處理下就行了

/**
         * HTTPS通信的網(wǎng)址(以https://開頭的網(wǎng)站)出現(xiàn)錯誤時
         * 證書錯誤攔截處理
         * 安卓7.0需要
         */
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            if(error.getPrimaryError() == android.net.http.SslError.SSL_INVALID ){// 校驗過程遇到了bug
                handler.proceed();      //忽略錯誤繼續(xù)加載
            }else{
                handler.cancel();       //取消加載
            }
        }

視頻全屏播放:安卓不像IOS一樣可以直接全屏播放,需要在WebChromeClient對其進行設(shè)置嘉栓,相當于是new 一個Fragment讓其來進行全屏播放

    /*** 視頻播放相關(guān)的方法 **/
        @Override
        public View getVideoLoadingProgressView() {
            FrameLayout frameLayout = new FrameLayout(MainActivity.this);
            frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            return frameLayout;
        }

        @Override
        public void onShowCustomView(View view, CustomViewCallback callback) {
            showCustomView(view, callback);
        }

        @Override
        public void onHideCustomView() {
            hideCustomView();
        }
image.png

代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_load"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="LOAD"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <WebView
            android:id="@+id/web_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </WebView>

        <ProgressBar
            android:id="@+id/pb_loading"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:visibility="gone"/>
    </RelativeLayout>

</LinearLayout>
public class MainActivity extends AppCompatActivity {

    @BindView(R.id.btn_load)
    Button mBtnLoad;
    @BindView(R.id.web_view)
    WebView mWebView;
    @BindView(R.id.pb_loading)
    ProgressBar mPbLoading;

    /** 視頻全屏參數(shù) */
    protected static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    private View customView;
    private FrameLayout fullscreenContainer;
    private WebChromeClient.CustomViewCallback customViewCallback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initWebView();
    }

    private void initWebView() {
        mWebView.setWebViewClient(new MyWebViewClient());       //設(shè)置在WebView中打開鏈接宏榕,不設(shè)置則調(diào)用自帶瀏覽器。主要針對View進行攔截處理
        mWebView.setWebChromeClient(new MyWebChromeClient());

        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);     //支持JS
        webSettings.setDomStorageEnabled(true);       //啟用dom內(nèi)存侵佃,防止js加載失敗
        webSettings.setAllowFileAccess(true);       //允許訪問文件
        webSettings.setSupportZoom(true);       //支持縮放
        webSettings.setLoadWithOverviewMode(true);      //是否啟動概述模式瀏覽界面麻昼,當頁面寬度超過WebView顯示寬度時,縮小頁面適應(yīng)WebView馋辈。默認false
        webSettings.setGeolocationEnabled(false);       //是否允許定位
        webSettings.setLoadsImagesAutomatically(true);      //是否加載圖片
//      webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);     //設(shè)置緩存模式
//      webSettings.setDefaultTextEncodingName("UTF-8");        //設(shè)置頁面的編碼格式抚芦,默認UTF-8
    }

    @OnClick(R.id.btn_load)
    public void onViewClicked() {
        mWebView.loadUrl("http://www.baidu.com");
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_BACK) {
            //優(yōu)先退出全屏播放
            if (customView != null) {
                hideCustomView();
                return true;
            } else {
                if (mWebView.canGoBack()) {
                    mWebView.goBack();      //返回上個頁面
                    return true;
                } else {
                    System.exit(0);     //退出程序
                }
            }
        }
        return super.onKeyDown(keyCode, event);
    }


    /**
     * 針對網(wǎng)頁進行攔截處理
     */
    public class MyWebViewClient extends WebViewClient{

        /**
         *可以實現(xiàn)對網(wǎng)頁中超鏈接的攔截
         */
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {

            //例:攔截電話網(wǎng)址,直接調(diào)用本地電話
            if (url.contains("tel:")){
                startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
                return true;
            }

            if (url.startsWith("http:") || url.startsWith("https:")) {
                view.loadUrl(url);
                return true;
            }
        /*  WebView.HitTestResult hitTestResult = view.getHitTestResult();
            //hitTestResult==null解決重定向問題
            if (!TextUtils.isEmpty(url) && hitTestResult == null) {
                view.loadUrl(url);
                return true;
            }*/

            return super.shouldOverrideUrlLoading(view, url);
        }

        /**
         *開始加載
         */
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            mPbLoading.setVisibility(View.VISIBLE);
        }

        /**
         * 結(jié)束加載
         */
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            mPbLoading.setVisibility(View.GONE);
        }

        /**
         * 加載錯誤的時候會產(chǎn)生這個回調(diào)
         */
        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            super.onReceivedError(view, errorCode, description, failingUrl);
            //TODO
        }

        /**
         * HTTPS通信的網(wǎng)址(以https://開頭的網(wǎng)站)出現(xiàn)錯誤時
         * 證書錯誤攔截處理
         * 安卓7.0需要
         */
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            if(error.getPrimaryError() == android.net.http.SslError.SSL_INVALID ){// 校驗過程遇到了bug
                handler.proceed();      //忽略錯誤繼續(xù)加載
            }else{
                handler.cancel();       //取消加載
            }
        }
    }

    /**
     * 針對瀏覽器攔截處理
     */
    public class MyWebChromeClient extends WebChromeClient{

        /**
         * 彈窗攔截
         */
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            return super.onJsAlert(view, url, message, result);
        }

        /**
         * 彈窗攔截
         */
        @Override
        public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
            return super.onJsConfirm(view, url, message, result);
        }

        /**
         * 彈窗攔截
         */
        @Override
        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
            return super.onJsPrompt(view, url, message, defaultValue, result);
        }

        /**
         * 加載進度攔截
         */
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            super.onProgressChanged(view, newProgress);
        }

        /**
         * 文件選擇
         */
        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
            selectImage();
            return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
        }

        /*** 視頻播放相關(guān)的方法 **/
        @Override
        public View getVideoLoadingProgressView() {
            FrameLayout frameLayout = new FrameLayout(MainActivity.this);
            frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            return frameLayout;
        }

        @Override
        public void onShowCustomView(View view, CustomViewCallback callback) {
            showCustomView(view, callback);
        }

        @Override
        public void onHideCustomView() {
            hideCustomView();
        }
    }

    /**
     * 圖片選擇
     */
    private void selectImage() {
        //TODO
    }

    /**
     * 視頻播放全屏
     */
    private void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {

        // if a view already exists then immediately terminate the new one
        if (customView != null) {
            callback.onCustomViewHidden();
            return;
        }
        getWindow().getDecorView();

        //獲取虛擬按鍵高度迈螟,防止遮擋
        if(ScreenUtils.hasNavBar(this)){
            COVER_SCREEN_PARAMS.setMargins(0,0,0,ScreenUtils.getNavigationBarHeight(this));
        }

        FrameLayout decor = (FrameLayout) getWindow().getDecorView();
        fullscreenContainer = new FullscreenHolder(this);
        fullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
        decor.addView(fullscreenContainer, COVER_SCREEN_PARAMS);
        customView = view;
        setStatusBarVisibility(false);
        customViewCallback = callback;
    }

    /**
     * 隱藏視頻全屏
     */
    private void hideCustomView() {
        if (customView == null) {
            return;
        }
        setStatusBarVisibility(true);
        FrameLayout decor = (FrameLayout) getWindow().getDecorView();
        decor.removeView(fullscreenContainer);
        fullscreenContainer = null;
        customView = null;
        customViewCallback.onCustomViewHidden();
        mWebView.setVisibility(View.VISIBLE);
    }

    /**
     * 全屏容器界面
     */
    static class FullscreenHolder extends FrameLayout {

        public FullscreenHolder(Context ctx) {
            super(ctx);
            setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
        }

        @Override
        public boolean onTouchEvent(MotionEvent evt) {
            return true;
        }
    }

    private void setStatusBarVisibility(boolean visible) {
        int flag = visible ? 0 : WindowManager.LayoutParams.FLAG_FULLSCREEN;
        getWindow().setFlags(flag, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
}

贈人玫瑰叉抡,手有余香。您的支持是我創(chuàng)作最大的動力!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末答毫,一起剝皮案震驚了整個濱河市褥民,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洗搂,老刑警劉巖消返,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異耘拇,居然都是意外死亡撵颊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門驼鞭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秦驯,“玉大人,你說我怎么就攤上這事挣棕。” “怎么了亲桥?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵洛心,是天一觀的道長。 經(jīng)常有香客問我题篷,道長词身,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任番枚,我火速辦了婚禮法严,結(jié)果婚禮上损敷,老公的妹妹穿的比我還像新娘。我一直安慰自己深啤,他們只是感情好拗馒,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著溯街,像睡著了一般诱桂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呈昔,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼项乒。 笑死媒殉,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的郭宝。 我是一名探鬼主播涡相,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼剩蟀!你這毒婦竟也來了催蝗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤育特,失蹤者是張志新(化名)和其女友劉穎丙号,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缰冤,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡犬缨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了棉浸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怀薛。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖迷郑,靈堂內(nèi)的尸體忽然破棺而出枝恋,到底是詐尸還是另有隱情,我是刑警寧澤嗡害,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布焚碌,位于F島的核電站,受9級特大地震影響霸妹,放射性物質(zhì)發(fā)生泄漏十电。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鹃骂。 院中可真熱鬧台盯,春花似錦、人聲如沸畏线。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽象踊。三九已至温亲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杯矩,已是汗流浹背栈虚。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留史隆,地道東北人魂务。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像泌射,于是被迫代替她去往敵國和親粘姜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容