在码农港湾
做一个实实在在的内行人

WebView&HTML5—–使用WebView播放HTML5视频文件

一、问题描述

HTML5提供了很多新的特性比如,视频播放、web本地存储、地理定位、应用缓存、Canvas等,但这些特性需要浏览器的支持,在Android应用中我们可以使用WebView构建Web应用,提供对HTML5技术的支持,WebView组件可以通过  setWebChromeClient()和setWebViewClient()加载WebViewClient与WebChromeClient。

WebViewClient主要帮助WebView处理各种通知、请求事件的

WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等

WebSeting通过该组件实现对浏览器的配置,如设置支持javascript脚本 、允许访问文件 、缩放控制按钮、支持缩放 等

下面就使用WebView播放HTML5的视频文件,效果如图

二、代码实现

1、编写HTML5WebView,重写WebView

复制代码
public class HTML5WebView extends WebView {
    private Context mContext;
    private MyWebChromeClient mWebChromeClient;
    private View mCustomView;
    private FrameLayout    mCustomViewContainer;
    private WebChromeClient.CustomViewCallback mCustomViewCallback;
    private FrameLayout mContentView;
    private FrameLayout    mBrowserFrameLayout;
    private FrameLayout    mLayout;
    static final String LOGTAG = "HTML5WebView";
    private void init(Context context) {
        mContext = context;        
        Activity a = (Activity) mContext;
        mLayout = new FrameLayout(context);
        mBrowserFrameLayout = (FrameLayout) LayoutInflater.from(a).
                inflate(R.layout.custom_screen, null);
        mContentView = (FrameLayout) mBrowserFrameLayout.findViewById(R.id.main_content);
        mCustomViewContainer = (FrameLayout) mBrowserFrameLayout.
                findViewById(R.id.fullscreen_custom_content);
        mLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
        mWebChromeClient = new MyWebChromeClient();
        setWebChromeClient(mWebChromeClient);
        setWebViewClient(new MyWebViewClient());
        //配置webview 
        WebSettings s = getSettings();
        s.setBuiltInZoomControls(true);//设置支持缩放 
        s.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        s.setUseWideViewPort(true);//设置此属性,可任意比例缩放
        s.setLoadWithOverviewMode(true);
        s.setSaveFormData(true);
        s.setJavaScriptEnabled(true);//支持js
        s.setGeolocationEnabled(true);
        s.setGeolocationDatabasePath("/data/data/com.jereh.html5webview/databases/");
        s.setDomStorageEnabled(true);
        mContentView.addView(this);
    }
    public HTML5WebView(Context context) {
        super(context);
        init(context);
    }
    public HTML5WebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    public HTML5WebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }
    public FrameLayout getLayout() {
        return mLayout;
    }
    public boolean inCustomView() {
        return (mCustomView != null);
    }
    public void hideCustomView() {
        mWebChromeClient.onHideCustomView();
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if ((mCustomView == null) && canGoBack()){
                goBack();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }
    private class MyWebChromeClient extends WebChromeClient {
        private Bitmap         mDefaultVideoPoster;
        private View         mVideoProgressView;
         // Android 使WebView支持HTML5 Video(全屏)播放的方法
        @Override
        public void onShowCustomView(View view, WebChromeClient.CustomViewCallback
                callback){
            HTML5WebView.this.setVisibility(View.GONE);
            // if a view already exists then immediately terminate the new one
            if (mCustomView != null) {
                callback.onCustomViewHidden();
                return;
            }
            mCustomViewContainer.addView(view);
            mCustomView = view;
            mCustomViewCallback = callback;
            mCustomViewContainer.setVisibility(View.VISIBLE);
        }
        
        @Override
        public void onHideCustomView() {
            
            if (mCustomView == null)
                return;           
            // Hide the custom view.
            mCustomView.setVisibility(View.GONE);
            // Remove the custom view from its container.
            mCustomViewContainer.removeView(mCustomView);
            mCustomView = null;
            mCustomViewContainer.setVisibility(View.GONE);
            mCustomViewCallback.onCustomViewHidden();
            HTML5WebView.this.setVisibility(View.VISIBLE);
        }
        
        @Override
        public Bitmap getDefaultVideoPoster() {
            if (mDefaultVideoPoster == null) {
                mDefaultVideoPoster = BitmapFactory.decodeResource(
                        getResources(), R.drawable.default_video_poster);
            }
            return mDefaultVideoPoster;
        }
        @Override
        public View getVideoLoadingProgressView() {
            if (mVideoProgressView == null) {
                LayoutInflater inflater = LayoutInflater.from(mContext);
                mVideoProgressView = inflater.inflate(R.layout.video_loading_progress, null);
            }
            return mVideoProgressView; 
        }
         @Override
         public void onReceivedTitle(WebView view, String title) {
            ((Activity) mContext).setTitle(title);
         }

         @Override
         public void onProgressChanged(WebView view, int newProgress) {
             ((Activity) mContext).getWindow().setFeatureInt(Window.FEATURE_PROGRESS,
                     newProgress*100);
         }
         @Override
         public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
             callback.invoke(origin, true, false);
         }
    }
    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
               return false;
        }
    }
    static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS =
        new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
复制代码

2、编写Activity,测试应用

复制代码
public class TestHTML5WebView extends Activity {
    HTML5WebView mWebView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mWebView = new HTML5WebView(this);
        
        if (savedInstanceState != null) {
            mWebView.restoreState(savedInstanceState);
        } else {
            mWebView.loadUrl("含有视频的Video标签的HTML5的页面");
            
        }   
        setContentView(mWebView.getLayout());
    }
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mWebView.saveState(outState);
    }
    
    @Override
    public void onStop() {
        super.onStop();
        mWebView.stopLoading();
    }
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (mWebView.inCustomView()) {
                mWebView.hideCustomView();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }
    
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
    }
}
复制代码
三、布局文件

1、  custom_screen.xml

复制代码
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android">
    <FrameLayout android:id="@+id/fullscreen_custom_content"
        android:visibility="gone"
        android:background="@color/black"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />
    <LinearLayout android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout android:id="@+id/error_console"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
        />
        <FrameLayout android:id="@+id/main_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
        />
    </LinearLayout>
</FrameLayout>
复制代码

2、video_loading_progress.xml

复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/progress_indicator"
         android:orientation="vertical"
         android:layout_centerInParent="true"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content">
       <ProgressBar android:id="@android:id/progress"
           style="?android:attr/progressBarStyleLarge"
           android:layout_gravity="center"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content" />
       <TextView android:paddingTop="5dip"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="center"
           android:text="@string/loading_video" android:textSize="14sp"
           android:textColor="?android:attr/textColorPrimary" />
 </LinearLayout>
复制代码

码农刷题必备工具 VS 码农进阶必读书籍

IT面试宝典宝典書城