现在已经2023年了,Android 14已出,低版本手机已经寥寥无几,但是还会有一些低版本非手机设备存在,这些手机的webview对于Vue2.0 、Vue3.0、ES6的兼容不够友好,有可能出现显示不出的情况。我们能想到的方案就是替换浏览器内核进行兼容。
之前比较流行的其他内核有两种:
-
Crosswalk
集成方式:blog.51cto.com/u_15950249/… 但是由于它们早已不再维护,而且包体积有点大。所以现在很少被使用
-
Tbs 是腾讯的一个浏览器内核,不仅能提供很好的兼容性,还能视频播放,文件处理等功能。
TBS其实并不是必然替换掉系统内核的,如果其X5内核没有下载安装完成,它还是使用的系统内核。
由于内核的体积较大,而且TBS本身还有流控机制,所以首次安装很可能会出现失败的情况,使用的还是系统内核。下图是它的一个初始化流程。
所以能找到一个不需要网络,能使用静态内核是一个比较稳妥的方式。因为新版本已经关闭了静态加载的方式,我们就使用老的版本来处理。
静态集成
配置sdk和内核
TBSSDK
链接: pan.baidu.com/s/1xanRVYU5… 提取码: jn3s
32位内核(适用于低版本手机)
链接: pan.baidu.com/s/1O7AxpdVY… 提取码: ubhw
64位内核
链接: pan.baidu.com/s/1t8g-4XQt… 提取码: 6kup
把SDK和内核文件放到对应文件夹:
在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>
说明
因为是旧版本的sdk,所以对新版的机型不一定兼容或者存在BUG。所以比较适用于低版本的手机做浏览器兼容。