静态集成腾讯TBS浏览服务

800 阅读3分钟

现在已经2023年了,Android 14已出,低版本手机已经寥寥无几,但是还会有一些低版本非手机设备存在,这些手机的webview对于Vue2.0 、Vue3.0、ES6的兼容不够友好,有可能出现显示不出的情况。我们能想到的方案就是替换浏览器内核进行兼容。

之前比较流行的其他内核有两种:

  • Crosswalk

    集成方式:blog.51cto.com/u_15950249/… 但是由于它们早已不再维护,而且包体积有点大。所以现在很少被使用

  • TBS

    Tbs 是腾讯的一个浏览器内核,不仅能提供很好的兼容性,还能视频播放,文件处理等功能。

TBS其实并不是必然替换掉系统内核的,如果其X5内核没有下载安装完成,它还是使用的系统内核。 由于内核的体积较大,而且TBS本身还有流控机制,所以首次安装很可能会出现失败的情况,使用的还是系统内核。下图是它的一个初始化流程。 image.png

所以能找到一个不需要网络,能使用静态内核是一个比较稳妥的方式。因为新版本已经关闭了静态加载的方式,我们就使用老的版本来处理。

静态集成

配置sdk和内核

TBSSDK

链接: pan.baidu.com/s/1xanRVYU5… 提取码: jn3s

32位内核(适用于低版本手机)

链接: pan.baidu.com/s/1O7AxpdVY… 提取码: ubhw

64位内核

链接: pan.baidu.com/s/1t8g-4XQt… 提取码: 6kup

把SDK和内核文件放到对应文件夹:

image.png

在app下面的build.gradle添加:

implementation fileTree(dir: "libs", include: ["*.aar"])

然后重新同步下项目

AndroidManifest.xml 添加权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

复制assets中的内核文件到android文件系统

// 目的目录文件路径
tbsCoreFilePath = getFilesDir().getPath() + File.separator + Constants.X5CORE_FILE_NAME;

File file = new File(tbsCoreFilePath);
// 如果文件已经存在,说明已经copy过了,无需再次操作
if (!file.exists()) {
    copyAssetsToFile();
    if (!file.exists()) {
        Log.e(TAG, "内核文件不存在,可能未copy成功,please try again!");
        return;
    }
}
/**
 * 复制 assets 目录下的core到Android文件目录
 * @throws IOException
 */
private void copyAssetsToFile() {
    try {
        AssetManager assetManager = getAssets();
        InputStream is = assetManager.open("tbs_core.tbs");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        baos.close();
        is.close();
        byte[] bytes = baos.toByteArray();
        String filePath = this.getFilesDir().getPath() + File.separator + Constants.X5CORE_FILE_NAME;
        FileOutputStream fos = new FileOutputStream(filePath);
        fos.write(bytes);
        fos.close();
    } catch (IOException e) {
        Log.d(TAG, "copyAssetsToFile: 失败");
    }

}

初始化tbs

如果文件已经存在就可以进行tbs初始化了。

private void initTbs() {
    // 这里配置内核文件路径和之前复制目的地一样
    TBSSdkManage tbsSdkManage = new TBSSdkManage.Builder(getApplicationContext())
            .localPath(tbsCoreFilePath).build();
    // 监听安装是否完成
    tbsSdkManage.setTbsListener(new TbsInstallListener() {
        @Override
        public void onDownloadFinish(int i) {

        }

        @Override
        public void onInstallFinish(int i) {
            // 安装完成后回调
            runOnUiThread(() -> {
                hideLoading();
                loadWebview();
            });
        }

        @Override
        public void onProgress(int i, int i1) {

        }

        @Override
        public void onError(int i, String s) {

        }
    });
    // 如果没有安装成功就进行安装,首次安装时间较长10s左右
    // 通常只要安装成功一次,下次便无需安装,可直接加载
    if (!tbsSdkManage.isInstallSuccess()) {
        Log.d(TAG, "initTbs: Tbs is not install, start install");
        tbsSdkManage.install();
    } else {
        Log.d(TAG, "initTbs: Tbs isInstallSuccess");
        runOnUiThread(() -> {
            hideLoading();
            loadWebview();
        });
    }
}

加载网页

这里需要注意不要在布局文件里面写WebView,采用动态加载的方式。因为如果TBS未安装完成就对webview初始化,那么安装完成后webview使用的内核仍然是系统的。

private void loadWebview() {
    if (webView != null) {
        return;
    }
    webView = new WebView(this);
    WebSettings settings = webView.getSettings();
    settings.setJavaScriptEnabled(true);
    settings.setCacheMode(WebSettings.LOAD_DEFAULT);
    settings.setDomStorageEnabled(true);
    settings.setDatabaseEnabled(true);
    settings.setAppCacheEnabled(true);
    settings.setAllowFileAccess(true);
    final String url = "https://www.baidu.com/";
    webView.loadUrl(url);
    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
    LinearLayout rootView = findViewById(R.id.root_view);
    rootView.addView(webView, layoutParams);
}

如果运行出现OutOfMemory的情况就在<application>中添加

<application
    android:largeHeap="true"
    android:hardwareAccelerated="false"
    .....>
</application>

demo

说明

因为是旧版本的sdk,所以对新版的机型不一定兼容或者存在BUG。所以比较适用于低版本的手机做浏览器兼容。