参考资料:
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 并不代表一定可以使用内核。内核由于包大小较大,需要依赖动态下发,故存在一定失败率
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。