2

参考资料:
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

  1. 去TBS官网下载sdk
    腾讯浏览服务 - SDK 下载
  1. 在android/app下创建libs然后把下载的sdk包放到文件夹里(把很长名字减短)
    image.png
  1. 用android studio打开,右键点击sdk包,Add As Library
    image.png
  1. 引入包
    在android/app/build.gradle

    def 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
    }
    ...
    
  1. 下载react-native-webview-tencentx5的代码,把android/src/main/java/indi/fan/webviewx5文件夹整个拷贝到自己写安卓原生组建的文件夹下(我的文件夹名字是webviewx)
    image.png
  1. 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;
  1. 将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()
         );
     }
    }
  2. 修改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);
     }
    }
  3. 引入到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;
         }
         ...
    }
  4. 在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内核,也可能为系统内核
                 }
             });
         }
         ...
    }
  5. 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" />
  6. AndroidManifest.xml增加Service声明

    <service 
      android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
      android:label="dexopt"
      android:process=":dexopt" >
    </service>
  7. 修改proguard-rules

    -dontwarn dalvik.**
    -dontwarn com.tencent.smtt.**
    
    -keep class com.tencent.smtt.** {
     *;
    }
    
    -keep class com.tencent.tbs.** {
     *;
    }
  8. 打包上架的时候审核会遇到要求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内核,也可能为系统内核
             }
         });
     }
     ... 
    }
    
  9. 初始化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();
     }
    }
  10. 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 并不代表一定可以使用内核。内核由于包大小较大,需要依赖动态下发,故存在一定失败率


perkz
51 声望28 粉丝

下一篇 »
Redux