博客 / 詳情

返回

React Native封裝tencentx5 Sdk的Webview

參考資料:
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 並不代表一定可以使用內核。內核由於包大小較大,需要依賴動態下發,故存在一定失敗率

user avatar zbh 頭像 jiasm 頭像
2 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.