腾讯TBSX5WebView - 替代系统自带WebView
官网: https://x5.tencent.com/docs/index.html
介绍:
腾讯浏览服务(TBS,Tencent Browsing Service)整合腾讯底层浏览技术和腾讯平台资源及能力,提供整体浏览服务解决方案。腾讯浏览服务面向应用开发商和广大开发者,提供浏览增强,内容框架,广告体系,H5游戏分发,大数据等服务,能够帮助应用开发商大幅改善应用体验,有效提升开发,运营,商业化的效率。
优点
传统系统内核(Webview)存在适配成本高、不安全、不稳定、耗流量、速度慢、视频播放差、文件能力差等问题,这是移动应用开发商在进行Hybrid App开发时普遍面临的难题。腾讯浏览服务基于腾讯X5内核解决方案(包括内核和云服务),能够有效解决传统移动web技术面临的普遍问题,同时能极大扩展应用(Hybrid App)内浏览场景的服务能力。
使用步骤
- 添加依赖 或者 官网下载jar包导入
- 一般自定义WebView控件再使用
- 在布局文件添加刚自定义好的控件
- 调用刚定义好的WebView
Demo - 带进度条的WebView
1、添加依赖 或者 官网下载jar包导入
添加依赖
//文件:app\build.gradle
implementation 'com.tencent.tbs.tbssdk:sdk:43697'
添加权限
//文件:app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 硬件加速对X5视频播放非常重要,建议开启 -->
<uses-permission android:name="android.permission.GET_TASKS" />
添加服务:该Service仅在TBS内核首次Dex加载时触发并执行dex2oat任务, 任务完成后自动结束
//文件:app/src/main/AndroidManifest.xml
<service
android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
android:label="dexopt"
android:process=":dexopt" />
享受页面视频的完整播放体验,页面的Activity需要声明android:configChanges=“orientation|screenSize|keyboardHidden”
避免输入法界面弹出后遮挡输入光标的问题:android:windowSoftInputMode=“stateHidden|adjustResize”
//文件:app/src/main/AndroidManifest.xml
<activity
android:name=".TBSX5WebView.BaseTencentWebActivity"
android:configChanges="orientation|screenSize|keyboardHidden">
android:windowSoftInputMode="stateHidden|adjustResize"
</activity>
在非硬绘手机和声明需要controller的网页上,视频切换全屏和全屏切换回页面内会出现视频窗口透明问题,需要如下设置
文件:\src\main\res\values\styles.xml
<item name="android:windowIsTranslucent">false</item>
2、一般自定义WebView控件再使用
文件:X5WebView.java
import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;
//注意WebView要继承com.tencent.smtt.sdk.WebView包下的
//并非android.webkit.WebView包
public class X5WebView extends WebView {
//设置顶部加载进度条
private ProgressBar mprogressBar;
//给自定义类创建构造方法,一般Alt+insert -> constructor -> 全部构造
// initWebView(context)为WebView作配置
public X5WebView(Context context) {
super(context);
initWebView(context);
}
public X5WebView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
initWebView(context);
}
public X5WebView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
initWebView(context);
}
public X5WebView(Context context, AttributeSet attributeSet, int i, boolean b) {
super(context, attributeSet, i, b);
initWebView(context);
}
public X5WebView(Context context, AttributeSet attributeSet, int i, Map<String, Object> map, boolean b) {
super(context, attributeSet, i, map, b);
initWebView(context);
}
// initWebView(context)为WebView作配置
private void initWebView(Context context) {
//添加进度条
mprogressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal);
//LayoutParams实现xml布局动态设置,主要设置View的位置(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 10);
mprogressBar.setLayoutParams(layoutParams);
mprogressBar.setProgress(0);
addView(mprogressBar);
//设置Settings,可直接照搬
WebSettings settings = this.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccess(true);
settings.setSupportZoom(true);
settings.setBuiltInZoomControls(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
settings.setUseWideViewPort(true);
settings.setSupportMultipleWindows(true);
settings.setAppCacheEnabled(true);
//此项影响网页的加载功能
settings.setDomStorageEnabled(true);
settings.setGeolocationEnabled(true);
settings.setAppCacheMaxSize(Long.MAX_VALUE);
settings.setPluginState(WebSettings.PluginState.ON_DEMAND);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
//初始化WebViewClient
setWebViewClient(new WebViewClient(){
//页面内跳转,禁止调用浏览器打开新链接
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String s) {
webView.loadUrl(s);
return super.shouldOverrideUrlLoading(webView, s);
}
});
//初始化WebChromeClient
setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView webView, int i) {
super.onProgressChanged(webView, i);
if (i == 100) {
mprogressBar.setVisibility(GONE);
} else {
if (mprogressBar.getVisibility() == GONE){
mprogressBar.setVisibility(VISIBLE);
}
mprogressBar.setProgress(i);
}
}
});
}
}
3、在布局文件添加刚自定义好的控件
文件:activity_base_tencen_web.xml
此处添加了一个ToolBar为后续添加返回主界面按键和用其他浏览器(非必须)
注意:提前学习ToolBar的使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context=".TBSX5WebView.BaseTencentWebActivity">
//ToolBar(非必须)
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</android.support.v7.widget.Toolbar>
<com.hong.frampractice.TBSX5WebView.X5WebView
android:id="@+id/myX5WebView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
4、调用刚定义好的WebView
public class BaseTencentWebActivity extends AppCompatActivity {
X5WebView myX5WebView;
String baseurl = "https://www.baidu.com";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base_tencen_web);
//x5内核初始化接口
initQbsdk();
//如果用到布局文件的ToolBar才需要设置(非必须)
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setTitle("实现文档");
myX5WebView = findViewById(R.id.myX5WebView);
//清理缓存和历史(非必须)
myX5WebView.clearCache(true);
myX5WebView.clearHistory();
//视频为了避免闪屏和透明问题,需要如下设置
getWindow().setFormat(PixelFormat.TRANSLUCENT);
//启用硬件加速
initHardwareAccelerate();
//加载url
myX5WebView.loadUrl(baseurl);
}
//x5内核初始化接口
private void initQbsdk() {
QbSdk.initX5Environment(this, new QbSdk.PreInitCallback() {
@Override
public void onViewInitFinished(boolean arg0) {
//x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
Log.d("app", "腾讯X5内核初始化回调 onViewInitFinished is " + arg0);
}
@Override
public void onCoreInitFinished() {
Log.d("app", "腾讯X5内核初始化回调 onCoreInitFinished");
}
});
}
//启用硬件加速:由于硬件加速自身并非完美无缺,所以Android提供选项来打开或者关闭硬件加速,默认是关闭。可以在4个级别上打开或者关闭硬件加速
private void initHardwareAccelerate() {
try {
if (Build.VERSION.SDK_INT >= 11) {
//Window级别硬件加速
getWindow()
.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}
} catch (Exception e) {
}
}
//设置返回键监听
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (myX5WebView != null && myX5WebView.canGoBack()) {
myX5WebView.goBack();
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
return super.onKeyDown(keyCode, event);
}
//释放资源,防止内存泄露
@Override
protected void onDestroy() {
if (myX5WebView != null) {
myX5WebView.destroy();
}
super.onDestroy();
}
//设置ToolBar菜单选项
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_webview, menu);
return true;
}
//Toolbar选择选项监听
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
break;
case R.id.share:
Intent intent = new Intent();
intent.setData(Uri.parse(baseurl));
intent.setAction(Intent.ACTION_VIEW);
startActivity(intent);
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
}
效果
来自官方的提醒 官方接入文档
- x5暂时不提供64位so文件,为了保证64位手机能正常加载x5内核,请参照如下链接修改相关配置https://x5.tencent.com/tbs/technical.html#/detail/sdk/1/34cf1488-7dc2-41ca-a77f-0014112bcab7
- 调整cookie的使用:
com.tencent.smtt.sdk.CookieManager和com.tencent.smtt.sdk.CookieSyncManager的相关接口的调用,在接入SDK后,需要放到创建X5的WebView之后(也就是X5内核加载完成)进行;否则,cookie的相关操作只能影响系统内核。 - 以下接口禁止(直接或反射)调用,避免视频画面无法显示:
webview.setLayerType()
webview.setDrawingCacheEnabled(true); - app 自定义 UA 的说明
如果 app 需要自定义 UA,建议采取在 SDK 默认UA 后追加 app UA 的方式示例:
webSetting.setUserAgentString(webSetting.getUserAgentString() + APP_NAME_UA);
其中 APP_NAME_UA 是 app 自定义 UA - app混淆时的处理
由于我们提供的 TBS jar 已经混淆过,所以 App 混淆时可以不再混淆我们的 TBS jar,或者也可以把我们的混淆策略 proguard 点击下载 加入 App 的混淆策略里注意:如果 App没有按照该规则混淆了 TBS jar,可能导致无法使用 x5内核 - Tbs视频播放器接入说明
TBS不仅提供了强大的网页浏览功能,更提供了强大的页面H5视频播放支持,播放器同时支持页面,小窗,全屏播放体验,强大的解码能力,包括mp4,rmvb,flv,avi等26种视频格式支持。
TBS播放器的播放场景不仅局限于H5页面播放,也可以接入一般的视频流链接,比如本地文件,网络的视频流链接。开发者如果想播放一个视频链接,在不自己开发播放器的前提下,一般做法是将视频的播放链接放到一个Intent里面,抛给系统的播放器进行播放,那么当你集成了TBS后,你只需要通过简单的方式接入视频播放调用接口,这样你不需要写任何一句关于播放器的代码,就可以享受一个本地播放器体验,播放视频再不需要Intent来跨App、跨进程的调用了。
下面是视频播放接入的步骤:
1.第一步
AndroidManifest需要如下的注册:
<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>
说明:VideoActivity是TBS自带的组件,需要App如上配置
2. 第二步
播放视频的调用接口
通过TbsVideo的静态方法,如下:
public static boolean canUseTbsPlayer(Context context)
//判断当前Tbs播放器是否已经可以使用。
public static void openVideo(Context context, String videoUrl)
//直接调用播放接口,传入视频流的url
public static void openVideo(Context context, String videoUrl, Bundle extraData)
//extraData对象是根据定制需要传入约定的信息,没有需要可以传如null
//extraData可以传入key: "screenMode", 值: 102, 来控制默认的播放UI
//类似: extraData.putInt("screenMode", 102); 来实现默认全屏+控制栏等UI
- 优化异常上报:
为了提高合作方的webview场景稳定性,及时发现并解决x5相关问题,当客户端发生crash等异常情况并上报给服务器时请务必带上x5内核相关信息。x5内核异常信息获取接口为:com.tencent.smtt.sdk.WebView.getCrashExtraMessage(context)。以bugly日志上报为例:
UserStrategy strategy = new UserStrategy(appContext);
strategy.setCrashHandleCallback(new CrashReport.CrashHandleCallback() {
public Map<String, String> onCrashHandleStart(int crashType, String errorType, String errorMessage, String errorStack) {
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
String x5CrashInfo = com.tencent.smtt.sdk.WebView.getCrashExtraMessage(appContext);
map.put("x5crashInfo", x5CrashInfo);
return map;
}
@Override
public byte[] onCrashHandleStart2GetExtraDatas(int crashType, String errorType, String errorMessage, String errorStack) {
try {
return "Extra data.".getBytes("UTF-8");
} catch (Exception e) {
return null;
}
}
});
CrashReport.initCrashReport(appContext, APPID, true, strategy);