WebView如何播放视频和全屏视频
前言
因为需求,需要在app中的webview实现播放视频以及全屏播放视频的功能,于是找了一个开源的WebView框架来使用,测试后一部分手机可以正常全屏,另一部分不行,于是决定新起一个项目测试代码。
写文章的时候,我会新开一个Android Project和添加一个Empty Activity,然后边敲边写。
最终的项目地址:https://github.com/wodongx123/WebViewDemo
1. 接入SDK
腾讯X5内核的下载地址:https://x5.tencent.com/tbs/sdk.html
写文章时的版本号为43697,更新时间为2019-8-8。
-
将下载后的文件中的jar包,放到app文件夹内部的lib文件夹下。然后在app内的build.gradle中添加代码。
apply plugin: 'com.android.application' android { //这些表示一开始就有的代码,不做改动 ....... sourceSets { main { jniLibs.srcDirs = ['libs'] } } } dependencies { ......... implementation files('libs/tbs_sdk_thirdapp_v4.3.0.1148_43697_sharewithdownloadwithfile_withoutGame_obfs_20190805_175505.jar') }
-
由于X5只支持32位,而我们的手机不出意外基本都是64位的,所以还要添加so包,在libs文件夹中创建armeabi,armeabi-v7a, mips, x86文件夹,再将liblbs.so文件分别放入文件夹下。(liblbs.so会在SDK里面,找不到可以善用文件搜索功能)
在module的build.gradle中添加内容。android { ...... defaultConfig { ....... ndk{abiFilters "armeabi", "armeabi-v7a", "mips", "x86"} } ........
-
修改AndroidManifest.xml文件,添加相关权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
-
然后开启硬件加速和添加全屏用的activity。
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" android:hardwareAccelerated="true"> <!--开启硬件加速--> <activity android:name=".MainActivity" android:configChanges="orientation|screenSize|keyboardHidden"> <!--在需要WebView的activity中添加configChanges,这里就直接用MainActivity--> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--添加全屏播放视频时的activity,直接复制下来就能使用--> <activity android:name="com.tencent.smtt.sdk.VideoActivity" android:configChanges="orientation|screenSize|keyboardHidden" android:exported="false" android:launchMode="singleTask" android:alwaysRetainTaskState="true"> <intent-filter> <action android:name="com.tencent.smtt.tbs.video.PLAY" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application>
2. 具体场景和代码实现
为了模拟实际开发场景,xml文件中不单纯只放一个WebView,添加了两个TextView。
<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"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Top text"
android:textSize="16dp"
android:layout_margin="10dp"
android:gravity="center"/>
<com.tencent.smtt.sdk.WebView
android:id="@+id/x5webview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bottom text"
android:textSize="16dp"
android:layout_margin="10dp"
android:gravity="center"/>
</LinearLayout>
整个项目只有MainActivity一个java文件,而且代码不多,直接贴代码。
由于视频容易过期,所以请自己上网寻找mp4文件的src。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
//这个就是html的内容,视频素材来源于网络,如果过期请自行找一个新的覆盖掉src部分
String htmlContent = "<p><video poster=\"\" controls=\"\" src=\"https://vdept.bdstatic.com/38644b66526b75555a694c6a76583939/5739454a47344471/1a85c1c1e61c7763897acbd3f5dbe6ec77f725e42cec7d805afe69a7078deed493953254765e01ea6b3c2c8a788ce350dd0619595480992cc9fe55cca6332792.mp4?auth_key=1582108594-0-0-5b8620541eb265e7a3b60b9045ab6dca\" width=\"100%\" height=\"300px\" class=\"note-video-clip\" preload=\"auto\"></video></p><p>测试视频测试视频测试视频</p>";
//注意,在import的时候,要使用com.tencent.smtt.sdk.WebView
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.x5webview);
initWebView();
}
private void initWebView() {
QbSdk.initX5Environment(this, new QbSdk.PreInitCallback() {
@Override
public void onCoreInitFinished() {
}
@Override
public void onViewInitFinished(boolean b) {
//true表示成功加载x5内核,false表示加载失败,使用内置的webview
Log.i(TAG, "onViewInitFinished: " + b);
}
});
webView.getSettings().setBlockNetworkImage(false);
webView.getSettings().setLayoutAlgorithm(com.tencent.smtt.sdk.WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
// 获取网络设置
WebSettings webSettings = webView.getSettings();
//启用应用缓存
webSettings.setAppCacheEnabled(true);
webSettings.setDatabaseEnabled(true);
//开启DOM缓存,qq
webSettings.setDomStorageEnabled(true);
//适应屏幕
webSettings.setLoadWithOverviewMode(true);
//这个一定要设置为false
webSettings.setSupportMultipleWindows(false);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
if (webView.getX5WebViewExtension() != null){ //视频全屏的相关配置
Toast.makeText(this, "如果弹出该Toast就能全屏", Toast.LENGTH_SHORT).show();
//没有弹出的情况下全屏按钮是灰色的不可点击
Bundle data = new Bundle();
data.putBoolean("standardFullScreen", false);// true表示标准全屏,false表示X5全屏;不设置默认false,
data.putBoolean("supportLiteWnd", true);// false:关闭小窗;true:开启小窗;不设置默认true,
data.putInt("DefaultVideoScreen", 1);// 1:以页面内开始播放,2:以全屏开始播放;不设置默认:1
webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
data);
}
//加载网页
webView.loadDataWithBaseURL("", htmlContent, "text/html", "UTF-8", "");
}
}
这样在运行的时候就可以加载视频了。
3. 踩坑
3.1 android.system.ErrnoException: chmod failed: EACCES (Permission denied)
在我做完如上操作之后,发现视频的全屏按钮是灰色的,并不能点击全屏进行播放。
于是我开始看logcat,果不其然在我翻logcat的时候发现这么一句报错。
W/FileUtils: Failed to chmod(/data/user/0/com.tencent.mm/app_tbs): android.system.ErrnoException: chmod failed: EACCES (Permission denied)
W/FileUtils: Failed to chmod(/data/user/0/com.tencent.mm/app_tbs): android.system.ErrnoException: chmod failed: EACCES (Permission denied)
这个报错是怎么一回事呢,其实是因为从Android6.0开始,权限除了要在AndroidManifest.xml中声明,还要在代码中请求,才能有相应的权限,于是在MainActivity中加入如下代码。
public class MainActivity extends AppCompatActivity {
........
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.x5webview);
//加载网页之前先申请权限
requestPermission();
initWebView();
}
private void initWebView() {
//省略已有代码
......
}
//踩坑,申请读写和网络
public static final int REQUEST_EXTERNAL_STORAGE = 1;
private String[] PERMISSON = {
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.INTERNET
};
private void requestPermission() {
int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, PERMISSON, REQUEST_EXTERNAL_STORAGE);
}
}
}
再次打开获得权限之后,就能全屏观看视频了。
3.2 Cleartext HTTP traffic to cfg.imtt.qq.com not permitted
获得权限之后,发现还是不能全屏观看,再次翻logcat,发现出现这么一段错误日志。
2020-02-19 18:42:53.236 18931-18966/com.example.webviewdemo W/System.err: java.io.IOException: Cleartext HTTP traffic to cfg.imtt.qq.com not permitted
具体解决方法请参考:安卓9.0 Cleartext HTTP traffic to XXX not permitted问题 - 简书
https://www.jianshu.com/p/fd0b0fd0e34c
这里用最简单的解决办法,打开AndroidManifest.xml,在Application中添加android:usesCleartestTraffic=“true”
<manifest>
<!--省略大量已有代码,只是为了表明添加代码的具体位置-->
........
<application
.......
android:usesCleartextTraffic="true"
>
.......
</application>
</manifest>
参考材料
Android中接入腾讯TBS浏览器WebView的入坑指南_移动开发_江子涛Tesla的专栏-CSDN博客
https://blog.csdn.net/u010312949/article/details/73136157
腾讯浏览服务-接入文档
https://x5.tencent.com/tbs/guide/sdkInit.html
解决open failed: EACCES (Permission denied)_移动开发_冬日-雪的博客-CSDN博客
https://blog.csdn.net/li18518326892/article/details/68486005
安卓9.0 Cleartext HTTP traffic to XXX not permitted问题 - 简书
https://www.jianshu.com/p/fd0b0fd0e34c