首先需要下载X5内核所需jar包,官网下载即可。
PS:在线/手动安装需要连接外网。
一、在线安装
在Application中初始化,会自动检测,没有则自动下载并安装。
package com.cashway.webviewdemo;
import android.app.Application;
import android.util.Log;
import com.tencent.smtt.sdk.QbSdk;
public class MainApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 初始化X5内核
initX5Tbs();
}
private void initX5Tbs() {
// 设置初始化回调
QbSdk.PreInitCallback callback = new QbSdk.PreInitCallback() {
@Override
public void onCoreInitFinished() {
// 内核初始化完成回调
Log.i("wmm", "内核初始化完成回调");
}
@Override
public void onViewInitFinished(boolean success) {
// 视图初始化完成回调
if (success) {
// 内核安装成功
Log.i("wmm", "X5内核安装成功");
} else {
// 内核安装失败
Log.i("wmm", "X5内核安装失败");
}
}
};
// 初始化X5内核
QbSdk.setDownloadWithoutWifi(true);//允许移动网络下载内核(大小 40-50 MB)
QbSdk.initX5Environment(getApplicationContext(), callback);
}
}
二、离线安装
离线安装不需要在Application中进行内核初始化操作。
1、下载内核文件
手动安装时,在控制台可看到以.tbs为结尾的文件包,点击下载到本地,将后缀改为.apk。
放置工程下,如图:
2、将内核文件复制到本地并进行安装
在activity进行内核检测,代码如下:
private void init() {
//初始化
webView = findViewById(R.id.web_view);
//检测X5内核
WebViewInstallTools.getInstance().detectX5Tbs(context, webView, new WebViewInstallTools.LocalInstallListener() {
@Override
public void onSuccessed() {
//安装成功
Log.d("X5", "X5内核成功");
}
@Override
public void onFailed(String message) {
//失败,手动安装
Log.d("X5", "X5内核安装失败" + message);
runOnUiThread(new Runnable() {
@Override
public void run() {
//离线安装失败,加载手动安装页面
webView.loadUrl("https://debugtbs.qq.com/");
}
});
}
});
}
package com.cashway.webviewdemo.tools;
import android.content.Context;
import android.util.Log;
import com.tencent.smtt.sdk.QbSdk;
import com.tencent.smtt.sdk.WebView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Timer;
import java.util.TimerTask;
/**
* @description X5内核安装工具类
*/
public class WebViewInstallTools {
private static WebViewInstallTools instance;
public static WebViewInstallTools getInstance() {
if (null == instance) {
synchronized (WebViewInstallTools.class) {
if (null == instance) {
instance = new WebViewInstallTools();
}
}
}
return instance;
}
/**
* 检测X5内核
*/
public void detectX5Tbs(Context context, WebView webView, LocalInstallListener installListener) {
if(webView.getX5WebViewExtension() != null){
Log.d("X5","X5内核已安装");
installListener.onSuccessed();
}else { // 离线安装X5内核
Log.d("X5","正在本地安装插件中");
startInstallX5LocationCore(context, new LocalInstallListener() {
@Override
public void onSuccessed() {
Log.d("X5","本地安装成功");
installListener.onSuccessed();
}
@Override
public void onFailed(String message) {
Log.d("X5","本地安装失败:" + message);
installListener.onFailed(message);
}
});
}
}
/**
* 安装本地内核
*/
private void startInstallX5LocationCore(Context context, LocalInstallListener installListener) {
final int num = 10;
int[] index = {0};
final int CORE_VERSION = 44286;//内核版本号
final String CORE_NAME = "tbs_core_44286.apk";//内核文件名称
final String path = context.getFilesDir().getParentFile().getParent();//存储路径
final String fileFolder = "x5tbs";
try {
Log.d("X5", ",内核版本号 CORE_VERSION = " + CORE_VERSION
+ ",内核文件名称 CORE_NAME = " + CORE_NAME
+ ",存储路径 path = " + path);
//复制X5tbs下的内核文件到终端
boolean isExitCore = copyAssetsToDir(context, fileFolder, path);
if (isExitCore) {
String installPath = path + File.separator + fileFolder + File.separator + CORE_NAME;
Log.d("X5", "安装内核地址:" + installPath);
//开始安装
QbSdk.installLocalTbsCore(context, CORE_VERSION, installPath);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
QbSdk.initX5Environment(context, new QbSdk.PreInitCallback() {
@Override
public void onCoreInitFinished() {
Log.d("X5", "onCoreInitFinished");
}
@Override
public void onViewInitFinished(boolean p0) {
Log.d("X5", "onViewInitFinished_p0=" + p0);
}
});
int version = QbSdk.getTbsVersion(context);
if (version > 0) {
Log.d("X5", "x5内核安装完成,版本号" + version);
timer.cancel();
installListener.onSuccessed();
} else {
Log.d("X5", "循环检验内核版本 " + version + ",计数:" + index[0]);
index[0]++;
if (index[0] > num) {
Log.d("X5", "超过" + num + "s");
timer.cancel();
installListener.onFailed("超过" + num + "s,取消安装");
}
}
}
}, 0, 1000);
}
} catch (Exception e) {
Log.d("X5", "本地离线内核安装异常,异常信息>" + e.getMessage());
installListener.onFailed("本地离线内核安装异常,异常信息:" + e.getMessage());
}
}
public interface LocalInstallListener {
public void onSuccessed();
public void onFailed(String message);
}
/**
* 从assets目录中复制整个文件夹内容,如考贝到 /sdcard/包名/files/目录中
* @param activity activity 使用CopyFiles类的Activity
* @param assetsFileFolder String 文件路径,如:/assets/aa
* @param sdcardFolder String 文件路径,如:/sdcard/
*/
private boolean copyAssetsToDir(Context activity, String assetsFileFolder, String sdcardFolder){
try {
String[] fileList = activity.getAssets().list(assetsFileFolder);
if(fileList!=null&&fileList.length>0) {//如果是目录
File file=new File(sdcardFolder + File.separator + assetsFileFolder);
if(file.isFile()&&!file.getParentFile().exists()) {
file.getParentFile().mkdirs();//如果文件夹不存在,则递归
}else{
file.getParentFile().mkdirs();
file.mkdirs();
}
for (String fileName:fileList){
assetsFileFolder = assetsFileFolder + File.separator + fileName;
copyAssetsToDir(activity, assetsFileFolder, sdcardFolder);
assetsFileFolder = assetsFileFolder.substring(0, assetsFileFolder.lastIndexOf(File.separator));
}
} else {//如果是文件
InputStream inputStream=activity.getAssets().open(assetsFileFolder);
File file = new File(sdcardFolder + File.separator + assetsFileFolder);
if(!file.exists() || file.length()==0) {
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
FileOutputStream fos=new FileOutputStream(file);
int len = -1;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1){
fos.write(buffer,0,len);
}
fos.flush();
inputStream.close();
fos.close();
// LogUtil.d(TAG,file.getPath()+"文件复制完毕");
} else {
// LogUtil.d(TAG,file.getPath()+"文件已存在,无需复制");
}
}
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}