參考資料:
react-native-webview-tencentx5
手把手教你一步步集成騰訊 X5 內核(Tencent TBS X5)
接入文檔
開發文檔
之前基於react-native-webview封裝的Canvas在比較老的android手機上沒法導出圖片canvas.toDataURL失效了,就想用react-native-webview-tencentx5去代替react-native-webview,但是react-native-webview-tencentx5不兼容react-native@0.70.所以只能借鑑react-native-webview-tencentx5重新去封裝一個webview。
- 去TBS官網下載sdk
騰訊瀏覽服務 - SDK 下載
- 在android/app下創建libs然後把下載的sdk包放到文件夾裏(把很長名字減短)
- 用android studio打開,右鍵點擊sdk包,
Add As Library
-
引入包
在android/app/build.gradledef webkit_version = rootProject.ext.has('webkitVersion') ? rootProject.ext.get('webkitVersion') : project.properties['ReactNativeWebView_webkitVersion'] <=add ... dependencies { ... implementation "androidx.webkit:webkit:$webkit_version" <=add implementation files('libs/tbs_sdk.jar') <=add } ...
- 下載react-native-webview-tencentx5的代碼,把
android/src/main/java/indi/fan/webviewx5文件夾整個拷貝到自己寫安卓原生組建的文件夾下(我的文件夾名字是webviewx)
-
RNX5WebViewManager.java裏修改java文件引入的路徑改成自己文件所在的路徑import indi.fan.webviewx5.RNX5WebViewModule.ShouldOverrideUrlLoadingLock.ShouldOverrideCallbackState; import indi.fan.webviewx5.events.TopLoadingErrorEvent; import indi.fan.webviewx5.events.TopHttpErrorEvent; import indi.fan.webviewx5.events.TopLoadingFinishEvent; import indi.fan.webviewx5.events.TopLoadingProgressEvent; import indi.fan.webviewx5.events.TopLoadingStartEvent; import indi.fan.webviewx5.events.TopMessageEvent; import indi.fan.webviewx5.events.TopShouldStartLoadWithRequestEvent; import indi.fan.webviewx5.events.TopRenderProcessGoneEvent;
-
將RNX5WebViewPackage.kt文件改成RNX5WebViewPackage.java
package com.xxxx.webviewx; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.Arrays; import java.util.Collections; import java.util.List; public class RNX5WebViewPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { return Arrays.<NativeModule>asList( new RNX5WebViewModule(reactContext) ); } public List<Class<? extends JavaScriptModule>> createJSModules() { return Collections.emptyList(); } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Arrays.asList( new RNX5WebViewManager() ); } } -
修改events文件裏的kt文件為java(以TopHttpErrorEvent為例)
package com.xxxx.webviewx.events; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; import com.facebook.react.uimanager.events.RCTEventEmitter; public class TopHttpErrorEvent extends Event<TopHttpErrorEvent> { public static final String EVENT_NAME = "topHttpError"; public int viewId; public WritableMap mEventData; public TopHttpErrorEvent(int viewId, WritableMap mEventData) { super(viewId); this.viewId = viewId; this.mEventData = mEventData; } public String getEventName() { return EVENT_NAME; } public boolean canCoalesce() { return false; } public short getCoalescingKey() { return 0; } public void dispatch(RCTEventEmitter rctEventEmitter) { rctEventEmitter.receiveEvent(this.viewId, this.EVENT_NAME, mEventData); } } -
引入到MainApplication.java裏
... import com.xxxx.webviewx.RNX5WebViewPackage; ... public class MainApplication extends Application implements ReactApplication { ... @Override protected List<ReactPackage> getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List<ReactPackage> packages = new PackageList(this).getPackages(); ... packages.add(new RNX5WebViewPackage()); return packages; } ... } -
在MainApplication.java初始化x5
... import com.tencent.smtt.sdk.QbSdk; import com.tencent.smtt.export.external.TbsCoreSettings; ... public class MainApplication extends Application implements ReactApplication { ... @Override public void onCreate() { super.onCreate(); initX5(); ... } ... private void initX5() { //解決首次使用時加載卡頓 HashMap map = new HashMap(); map.put(TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER, true); map.put(TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE, true); QbSdk.initTbsSettings(map); //流量也能下載 QbSdk.setDownloadWithoutWifi(true); //x5內核初始化接口 QbSdk.initX5Environment(getApplicationContext(), new QbSdk.PreInitCallback() { @Override public void onViewInitFinished(boolean isX5) { //x5內核初始化完成的回調,為true表示x5內核加載成功,否則表示x5內核加載失敗,會自動切換到系統內核。 } @Override public void onCoreInitFinished() { // 內核初始化完成,可能為x5內核,也可能為系統內核 } }); } ... } -
AndroidManifest.xml里加入權限聲明
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> -
AndroidManifest.xml增加Service聲明
<service android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService" android:label="dexopt" android:process=":dexopt" > </service> -
修改proguard-rules
-dontwarn dalvik.** -dontwarn com.tencent.smtt.** -keep class com.tencent.smtt.** { *; } -keep class com.tencent.tbs.** { *; } -
打包上架的時候審核會遇到要求x5初始化在確認隱私協議之後,我嗎幾把初始化的方法寫在
RNX5WebViewModule.java裏在確認隱私協議之後調用package com.xxx.webviewx; import java.util.HashMap; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ActivityEventListener; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.tencent.smtt.export.external.TbsCoreSettings; import com.tencent.smtt.sdk.QbSdk; // import com.facebook.react.bridge.Callback; @ReactModule(name = RNX5WebViewModule.MODULE_NAME) public class RNX5WebViewModule extends ReactContextBaseJavaModule implements ActivityEventListener { ... // 加這個 private ReactApplicationContext context; ... public RNX5WebViewModule(ReactApplicationContext reactContext) { super(reactContext); // 加這個 this.context = reactContext; reactContext.addActivityEventListener(this); } ... // 也可以傳入回調 final Callback callback 把初始化的結果返回出來,沒必要,不成功自己會變成react-native-webview @ReactMethod public void initX5() { HashMap map = new HashMap(); map.put(TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER, true); map.put(TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE, true); QbSdk.initTbsSettings(map); QbSdk.setDownloadWithoutWifi(true); //x5內核初始化接口 QbSdk.initX5Environment(context, new QbSdk.PreInitCallback() { @Override public void onViewInitFinished(boolean isX5) { //x5內核初始化完成的回調,為true表示x5內核加載成功,否則表示x5內核加載失敗,會自動切換到系統內核。 } @Override public void onCoreInitFinished() { // 內核初始化完成,可能為x5內核,也可能為系統內核 } }); } ... } -
初始化ts部分
import React from "react"; import { Platform } from 'react-native'; const NativeRNX5WebView = Platform.OS === "ios" ? {} : (NativeModules.RNX5WebView || {}); // 在同意隱私協議之後 initX5() export function initX5 () { if (NativeRNX5WebView.initX5) { NativeRNX5WebView.initX5(); } } -
WebviewX5的組件封裝參考react-native-webview-tencentx5
import { requireNativeComponent } from 'react-native'; import WebView from "react-native-webview"; const RNX5WebView = Platform.OS === "ios" ? WebView : requireNativeComponent('RNX5WebView'); ...
接入TBS SDK 並不代表一定可以使用內核。內核由於包大小較大,需要依賴動態下發,故存在一定失敗率