由於X5內核打包后有30多M,x5官網文檔也着重提醒:“由於內核體積較大,官網SDK默認為靜默下載方案,首次使用需要在網絡中靜默下載約30M的內核,可能存在一定的加載失敗率,目前線上加載成功率約為90%。如果您有業務需要強依賴X5內核相關功能,請使用靜態集成方式進行集成”。
當某些特殊app必須可靠加載X5內核時(非普通用戶使用,沒有裝微信),等待網絡慢慢下載還不一定成功,那就太廢了;似乎靜態集成給了一條活路。
關鍵就在於這個“靜態集成”,整個x5官網,除了常見問題中有提到,其他任何地方都找不到如何靜態集成,更找不到SDK;后面發現是早年有提供文檔和下載,不過后面就關閉了,文檔也刪了;也許是用的人多,又不掙錢,KPI下的產物吧,沒利誰給你免費維護。
經過搜羅歷史資料(GitHub搜代碼真穩的一比),結合下載到的老版本靜態集成SDK,經過一番摸索,實現了:用老版本的jar + 最新的TBS X5內核,進行靜態集成,將內核直接打包進APK。
前情提要
本篇文章只針對X5內核的靜態集成,將30多M內核直接打包進Apk,TBS X5官網已經沒有相關資料了;如果你不是要把內核打包進Apk,請直接閱讀官網 https://x5.tencent.com/ 文檔就行了,不用折騰。
第一步:下載老版本SDK得到jar
獲取SDK
當前時間:2020-08-07,能找到的最新的一個靜態集成SDK,看里面文件名時間是2017-10-11,雖然老了點,但是能用來加載最新的X5內核,沒有問題。
下載后,只需要提取里面的tbs_sdk_thirdapp_v3.5.0.1063_43500_staticwithdownload_withoutGame_obfs_20171011_195714.jar
,另外一個apk文件是內核(這個內核太老,就不要了)。
如果上面地址失效了,我在github里面存了一份jar,地址:
https://github.com/xiangyuecn/Docs/blob/master/H5/靜態集成騰訊TBS X5內核WebView,從微信提取新版30M瀏覽器內核打包進apk_files/tbs_sdk_thirdapp_v3.5.0.1063_43500_staticwithdownload_withoutGame_obfs_20171011_195714.jar
SHA1: BB40F495C4CC39F41DBE34124F443B3EC43073EC
集成SDK
把得到的這個tbs_sdk_*.jar copy到項目的libs目錄中(如果你已經導入了新版的tbs_sdk_*.jar
,把新版刪掉就行,它們沒有QbSdk.preinstallStaticTbs靜態內核加載方法)。
這樣SDK就集成好了(見文末圖),此時就算不集成靜態內核也能正常運行,就是x5加載不太穩定。
步驟二、下載提取最新TBS X5內核
有兩種方法,一個是從微信里面提取;另外一個就是app內訪問tbs調試頁面,然后安裝新內核,再提取。
方法1:從微信中提取
微信中打開http://debugtbs.qq.com
,進入界面后點擊拷貝內核
按鈕,會彈出保存的路徑(參考頂上【圖3】),打開這個路徑后提取里面的core_private/x5.debug.tbs
這個文件(如果沒有這個文件,就把彈出的路徑中所有文件都copy出來,把30M以上文件都改成zip,能打開的就是了),其實這個是一個apk/zip文件,30多M,解壓后得到一堆so和jar等文件,先復制出來再說,文件名加一個zip后綴。
X5官網中 關於TBS
-> 平台適配
中已經寫明了只支持armeabi、armeabi-v7a、arm64-v8a
這3種架構,因此對於x86
等架構是不支持的(AS模擬器),拋開模擬器,大部分似乎只需提供armeabi
架構就ok了。
微信中提取出來的這個內核的架構可能是arm64-v8a
,如果你要armeabi
架構,請用下面方法2來獲取內核。
方法2:App內內訪問tbs調試頁安裝新內核
集成了上面的老版本SDK后,你的App就可以通過訪問http://debugtbs.qq.com
頁面來手動下載最新
X5內核(如果下載不了,嘗試改回新版本SDK下載,然后再改回來)。點擊安裝線上內核
(參考頂上【圖1】),它會自動識別App的架構,下載到armeabi
或者arm64-v8a
架構的TBS內核包,下載完后重啟App就可以進行內核提取操作了。
這就有兩種途徑獲取到內核包了,一個是在安裝時監控App的網絡請求,得到下載地址;另外一個就是和微信里面一樣,點擊拷貝內核
按鈕,參考上面微信的流程。
這里提供我拿到的一個內核下載地址:
http://tbs.imtt.qq.com/release/tbs_core_045318_20200714112122_nolog_fs_obfs.tbs
30多M,內核版本:45318(20200714112122),Chrome 77
步驟三、集成內核到App中
解壓內核得到so
你提取到內核文件就是一個apk文件,直接zip解壓就行了,里面有lib
+ assets
兩個目錄,我們要把這兩個目錄內的所有文件合到一起放到一個目錄再操作:
lib
目錄內可能是armeabi
或者 arm64-v8a
,不同架構是因為是根據你App架構(或微信) + 手機支持的架構由TBS自動下載的,如果你需要的架構類型和lib
里面的不同,那么請參考上面重新提取內核。
將lib/arm*內的so文件復制出來,和assets/webkit
內的文件放到一起,總共一起共40來個文件。
so改名
將剛才復制到一起的一堆文件,文件名統統加上libtbs.
前綴 + .so
后綴,比如abc.so
文件,改名后變成libtbs.abc.so.so
,jar、conf文件也不例外。
附:CMD命令行批量改名
::直接在當前這堆文件的目錄執行下面代碼,批量改名
for /F %i in ('dir /A:-D /B') do move %i "libtbs.%i.so"
集成內核
將改好名的所有文件,copy到項目的src/main/jniLibs/armeabi
目錄中(如果是arm64-v8a
的一樣copy),這樣內核就集成好了(見文末圖)。下面我們只需要在app運行時激活這個內核就ok了。
記得build.gradle中配置上ndk,如
defaultConfig {
...
ndk {abiFilters "armeabi","x86"} //真機 + 模擬器,談性能?不如喂狗
}
激活X5內核
不要用QbSdk.initX5Enviroment方法,改用QbSdk.preinstallStaticTbs方法。
在顯示webview前,你要先把X5內核安裝好(我管他叫激活)。代碼就一句話,你最好在當前Activity(你得激活完后再手動創建WebView)里面,或者在Application(似乎沒有Activity里面激活來的穩定)里面執行:
//此方法非常耗時,應當開個線程
QbSdk.preinstallStaticTbs(getApplicationContext());
//這里就可以安全的創建WebView了,只要你的ABI架構沒有問題,那么這里一定能加載到X5內核
簡單點就在Activity里面激活就行,省得死活加載不了,比如這樣子:
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
/*注意,你的布局里面不要有任何X5相關的東西,只留一個來容器放X5的WebView即可
<LinearLayout
android:id="@+id/webviewBox"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
*/
setContentView(R.layout.mylayout);
//X5的WebView用動態創建,當內核准備好時,在創建,可能是異步也可能是同步操作
if(QbSdk.canLoadX5(getApplicationContext())){
Log.i("TBS_X5","已安裝好,直接顯示");
createWebview();
}else{
Log.i("TBS_X5","新安裝");
new Thread(new Runnable() {
@Override
public void run() {
boolean ok=QbSdk.preinstallStaticTbs(getApplicationContext());
Log.i("TBS_X5","安裝成功:"+ok);
runOnUiThread(new Runnable() { @Override public void run() {
createWebview();
}});
}
}).start();
}
}
private void createWebview(){
//手動創建WebView,顯示到容器中,這樣就能保證WebView一定是在X5內核准備好后創建的
WebView webView = new WebView(getApplicationContext());
LinearLayout.LayoutParams css=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
((LinearLayout)findViewById(R.id.webviewBox)).addView(webView, css);
//...其他代碼
}
}
/*如果放到Application.onCreate里面激活,似乎會有點問題,測試中發現后面Activity沒有加載到X5內核,移到Activity就瞬間好了。這里還是放一個例子吧
public class MyApp extends Application{
public static Boolean X5Ok=null;
@Override
public void onCreate(){
super.onCreate();
new Thread(new Runnable() {
@Override
public void run() {
//Application里安裝就算OK了也不保證一定能用
X5Ok=QbSdk.preinstallStaticTbs(getApplicationContext());
}
}).start();
}
}
*/
其他的一些配置,參考官網就OK
權限
<uses-permission ....
抱歉,先毛權限也不給。你App本來需要什么權限,就給什么權限(網絡、錄音、攝像頭),不用管X5官網的那一坨。
等他崩潰再一個個給,似乎只要INTERNET、ACCESS_NETWORK_STATE權限就夠了。
包名替換
Java文件中:android.webkit.WebView
-> com.tencent.smtt.sdk.WebView
。
布局文件中:<WebView />
-> <com.tencent.smtt.sdk.WebView />
詳細的包名替換閱讀X5官網。
WebView網頁權限
當網頁訪問攝像頭、麥克風時,X5默認會彈一個確認對話框,自己的App網頁就沒有這么多條條框框了,可以靜默授權:
//webkit是 WebChromeClient.onPermissionRequest 處理網頁授權
//x5是 IX5WebChromeClientExtension.onPermissionRequest 處理網頁授權
webView.setWebChromeClientExtension(new IX5WebChromeClientExtension() {
...
@Override
public boolean onPermissionRequest(String s, long l, MediaAccessPermissionsCallback callback) {
你的App攝像頭、錄音權限申請( 申請成功回調{
long allowed = 0;
allowed = allowed | MediaAccessPermissionsCallback.ALLOW_AUDIO_CAPTURE | MediaAccessPermissionsCallback.ALLOW_VIDEO_CAPTURE;
boolean retain = true;
callback.invoke(s, allowed,retain);
});
return true;
}
...
});
首次初始化冷啟動優化
用不着,QbSdk.initX5Enviroment方法也用不着。
混淆、文件、視頻
閱讀X5官網文檔。
結束語
歡迎關注我的GitHub:
H5、Hybrid App錄音庫,支持mp3、wav、語音識別:https://github.com/xiangyuecn/Recorder
省市區鎮數據,提供坐標、邊界,和shp、geojson、sql支持:https://github.com/xiangyuecn/AreaCity-JsSpider-StatsGov
如果本篇文章對你有幫助,您也可以到上面倉庫中對作者進行打賞~