背景
在Android开发中,遇到了如下问题:Activity内嵌WebView,加载有视频的页面时,视频无法全屏播放。全屏按钮不显示或者灰显。
故记录一下此次问题解决过程。
问题定位
在Android官方文档上对问题所述场景有如下解释:
其大意为:
1. 要打开硬件加速
2. 设置 WebChromeClient ,并实现 onShowCustomView() 方法和onHideCustomView()方法。
3. 要支持全屏
查看代码,并没有打开硬件加速,且WebChromeClient 虽然设置了,但是没有实现onShowCustomView() 方法和onHideCustomView()方法。关于第三点全屏,暂时没有看懂。
我们先修改前两点:
- 打开硬件加速:在Manifest中,对应的Activity添加
android:hardwareAccelerated = "true"
。 - Activity中,对WebView进行如下设置:
//添加浏览器代理
mWvContent.setWebChromeClient(new WebChromeClient() {
······
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
}
@Override
public void onHideCustomView() {
super.onHideCustomView();
}
});
设置好后,满心欢喜的运行,全屏按钮出来啦!然而点击之后,依然无法播放···
好吧,继续定位。我们已经确认,官方对h5视频的适配要求中,前两条我们已经满足了,唯有第三条还没有满足。在查阅资料后,发现WebView在点击全屏按钮后,会调用onShowCustomView方法。而全屏的视频会在其参数View view
中进行渲染。所以我们需要在Activity中写一个容器,在onShowCustomView触发后,将其view
传入该容器,且使APP横屏,容器全屏显示。
接下来修改代码:
布局修改(fl_video为新增的容器,用于全屏时展示):
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/fl_video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<WebView
android:id="@+id/wv_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
重新实现onShowCustomView与onHideCustomView(mCustomView ):
private FrameLayout mLayout; // 用来显示视频的布局
private View mCustomView; //用于全屏渲染视频的View
private WebChromeClient.CustomViewCallback mCustomViewCallback;
······
mLayout = findViewById(R.id.fl_video);
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
//如果view 已经存在,则隐藏
if (mCustomView != null) {
callback.onCustomViewHidden();
return;
}
mCustomView = view;
mCustomView.setVisibility(View.VISIBLE);
mCustomViewCallback = callback;
mLayout.addView(mCustomView);
mLayout.setVisibility(View.VISIBLE);
mLayout.bringToFront();
//设置横屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
@Override
public void onHideCustomView() {
super.onHideCustomView();
if (mCustomView == null) {
return;
}
mCustomView.setVisibility(View.GONE);
mLayout.removeView(mCustomView);
mCustomView = null;
mLayout.setVisibility(View.GONE);
try {
mCustomViewCallback.onCustomViewHidden();
} catch (Exception e) {
}
// titleView.setVisibility(View.VISIBLE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏
}
接下来Manifest中配置横竖屏切换不走onCreate,防止h5重新加载:
manifest:android:configChanges="keyboardHidden|orientation|screenSize"
Activity横竖屏切换进行UI的调整:
/**
* 横竖屏切换监听
*/
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
switch (config.orientation) {
case Configuration.ORIENTATION_LANDSCAPE:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
mToolbar.setVisibility(View.GONE);
break;
case Configuration.ORIENTATION_PORTRAIT:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
mToolbar.setVisibility(View.VISIBLE);
break;
}
}
调试代码,全屏功能OK。
注意:
在Actiity销毁的时候一定要销毁WebView,否则会造成WebView中的视频在Activity销毁后继续播放:
@Override
protected void onDestroy() {
super.onDestroy();
//清空所有cookie
CookieSyncManager.createInstance(WebActivity.this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
CookieSyncManager.getInstance().sync();
mWvContent.setWebChromeClient(null);
mWvContent.setWebViewClient(null);
mWvContent.getSettings().setJavaScriptEnabled(false);
mWvContent.clearCache(true);
mWvContent.destroy();
}