1. 程式人生 > >webview 載入h5頁面,播放視訊+全屏,實現簡單封裝

webview 載入h5頁面,播放視訊+全屏,實現簡單封裝

前段時間專案中用到了h5。從目前的市場來看,原生和h5的結合受到很多公司的歡迎,剛好最近微信也推出了它自己的“小程式”,這在Android程式設計師之間也掀起了波瀾,引起大家討論。

個人覺得Google提供的webview有很多的坑,我這次就踩了不少,比如在某些版本的系統上某個方法不會執行,或者執行的順序不一樣,有的方法會多執行一次,說白了就是相容性做的很差,究其主要原因,是Android4.4前後webview 的核心發生了變化。那麼Google難道沒有發現這個問題?Google肯定發現了,那為什麼還做的這麼差勁呢,個人覺得有這麼一個原因吧,Google想大力推廣自己的Android,如果webview做的很好了,h5的應用勢必會越來越廣泛,勢必會有很多不大的公司在一個app中更多的選擇使用h5。因為它開發方便,維護成本更低,有了問題不用版本迭代,在後臺直接就改了(這些是現在原生app面臨的一大問題,但是有解決辦法)。

下面就來說說我在這次webview開發中遇到的問題,和對webview的一個簡單的封裝。

首先上效果圖:



下面主要說下實現的方法:

先需要一個webview,這個webview用來載入h5的頁面,在半屏播放的時候也用這個webview,全屏的時候用一個framelayout,此時需要把webview隱藏了,xml的大概佈局如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
        <FrameLayout
            android:id="@+id/video_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone" >
        </FrameLayout>
        <WebView
            android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" 
            />
</RelativeLayout>

這兒其實還可以自定義一個404顯示的view,在沒網或者url載入失敗的時候去顯示,這樣使用者的體驗效果要好一點。

接下來就是webview和fragmentlayout的獲取

videoview = (FrameLayout) findViewById(R.id.video_view);
webview = (WebView) findViewById(R.id.webview);
下面就是webview的setting的一個設定了,在這裡沒什麼好說的,建議大家一定要開啟快取。本人在這兒做的時候,在程式碼中通過判斷sdk的版本,開啟了硬體加速的功能,但是導致的原因是隻有聲音,沒有影象,不設定webview的硬體加速就沒問題,個人感覺主要和h5有很大的關係。

其次為了提高渲染的速度,建議大家可以開啟gpu的渲染

getWindow().setFlags(//強制開啟GPU渲染
				WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
				WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

接下來就是設定webview的檢視
webview.setWebViewClient(new CustomWebViewClient());

我們在程式碼中自定義一個類CustomWebViewClient,主要實現其幾個方法,實現對webview開始載入,載入完成,載入失敗回撥的處理
private final class CustomWebViewClient extends WebViewClient {
        //url載入失敗
        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            super.onReceivedError(view, errorCode, description, failingUrl);
<span style="white-space:pre">	</span>    //做自己的一些處理,比如載入我們自定義的view或者給使用者一個提示
        }
<span style="white-space:pre">	</span>//頁面載入完成的時候呼叫
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        @SuppressLint("NewApi")
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
<span style="white-space:pre">	</span>   //可以做一些載入完成的處理,比如隱藏正在載入的動畫
        }
<span style="white-space:pre">	</span>//頁面開始載入的時候呼叫
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
<pre name="code" class="java" style="font-size: 18px;"><span style="white-space:pre">	</span>  //可以做一些載入完成的處理,比如顯示正在載入的動畫
} }

最後就到視訊播放了,視訊全屏播放的時候需要用到一個類WebChromeClient,我們只要自定義一個類,去實現它裡面的2個方法即可

/**
     * 處理Javascript的對話方塊、網站圖示、網站標題以及網頁載入進度等
     *
     * @author
     */
    public class xWebChromeClient extends WebChromeClient {
        private Bitmap xdefaltvideo;
        private View xprogressvideo;

        @Override
        // 播放網路視訊時全屏會被呼叫的方法
        public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
            if(a!=null){
                a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
            if(webview!=null){
                webview.setVisibility(View.GONE);
            }
            // 如果一個檢視已經存在,那麼立刻終止並新建一個
            if (xCustomView != null&&callback!=null) {
                callback.onCustomViewHidden();
                return;
            }
            if (view != null&&videoview!=null) {
                videoview.addView(view);
                xCustomView = view;
            }
            if(xCustomViewCallback!=null){
                xCustomViewCallback = callback;
            }
            if(videoview!=null){
                videoview.setVisibility(View.VISIBLE);
            }
        }

        @SuppressLint("NewApi")
        @Override
        // 視訊播放退出全屏會被呼叫的
        public void onHideCustomView() {
            if (xCustomView == null||videoview==null)// 不是全屏播放狀態
                return;
            videoview.removeView(xCustomView);
            if(a!=null){
                a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            }
            xCustomView.setVisibility(View.GONE);
            xCustomView = null;
            videoview.setVisibility(View.GONE);
            if(xCustomViewCallback!=null){
                xCustomViewCallback.onCustomViewHidden();
            }
            if(webview!=null){
                webview.setVisibility(View.VISIBLE);
            }
            if(setting!=null){
                setting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);// 排版適應螢幕
            }
        }

        // 視訊載入新增預設圖示
        @Override
        public Bitmap getDefaultVideoPoster() {
            if (xdefaltvideo == null) {
                xdefaltvideo = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
            }
            return xdefaltvideo;
        }
        // 視訊載入時程序loading
        @SuppressLint("InflateParams")
        @Override
        public View getVideoLoadingProgressView() {
            if (xprogressvideo == null) {
                LayoutInflater inflater = LayoutInflater.from(a);
                xprogressvideo = inflater.inflate(R.layout.video_loading_progress, null);
            }
            return xprogressvideo;
        }

        // 網頁標題
        @Override
        public void onReceivedTitle(WebView view, String title) {
            // a.setTitle(title)
            //view.getSettings().setBlockNetworkImage(false);
        }

        @Override
        // 當WebView進度改變時更新視窗進度
        public void onProgressChanged(WebView view, int newProgress) {
            a.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, newProgress * 100);
        }
    }

提示:在全屏播放的activity上一定要加上android:configChanges="orientation|keyboardHidden|screenSize"

到這兒視訊播放也就差不多了,但是相容性還是大問題,這兒就需要我們自己慢慢調了。在這兒我給大家推薦一個相容性很好的webview框架,就是騰訊X5,我自己也下載的demo然後跑了一下,確實要比Google的webview牛掰了很多,目前在微信,QQ,QQ瀏覽器中解析h5都用的X5,這是他們自己寫的核心,在相容性,安全性,美觀性上都有很大的提升。