React Native 橋接原生 iOS 以及 Android 獲取 APP 版本號

蘆葦科技App技術團隊發表於2019-03-01

在使用React Native進行跨平臺開發過程中,或多或少需要涉及到原生開發,這裡主要說一下如何橋接原生 iOS 以及 Android,在此以獲取 APP 版本號為例。

iOS 橋接

iOS 橋接比較簡單,只需要建立一個 Module 類,實現 RCTBridgeModule 協議就好。
首先我們需要建立一個 RNBridgeManager 類

RNBridgeManager.h 中的程式碼:

#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>

@interface RNBridgeManager : NSObject <RCTBridgeModule>

@end
複製程式碼

然後在 RNBridgeManager.m 中實現相應方法

為了實現 RCTBridgeModule 協議,你的類需要包含 RCT_EXPORT_MODULE()巨集。這個巨集也可以新增一個
指定引數用來指定在使用 Javascript 中訪問這個模組的名字

RNBridgeManager.m 中的程式碼

#import "RNBridgeManager.h"
@implementation RNBridgeManager

@synthesize bridge = _bridge;

RCT_EXPORT_MODULE(ToolModule);
//  對外提供呼叫方法,Callback
RCT_EXPORT_METHOD(getAppVersion:(RCTResponseSenderBlock)callback)
{
  NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];//獲取專案版本號
  callback(@[[NSNull null],version]);
}

@end

複製程式碼

最後在RN中呼叫

import React, { Component } from `react`;
import { NativeModules } from `react-native`;

var iOSToolModule = NativeModules.ToolModule;

export default class Me extends Component {
    constructor(props) {
        super(props);
        this.state = {
            version: ``, 
        }

        this.getVerSion();
    }

    // 獲取版本號
    getVerSion() {
    iOSToolModule.getAppVersion((error,event)=>{
                if(error){
                    console.log(error)
                }else{
                    this.setState({
                        version:event
                    })
                }
            }) 
    }
 }  
複製程式碼

至此,iOS 部分的橋接工作就全部完成了。

Android

Android 相對 iOS 較為複雜,我們首先需要在 Android/app/src/main/java/com 資料夾下新建一個 reactnative 資料夾,在該資料夾下建立 RNBridgeManager.java 檔案以及RNReactPackage.java 檔案,具體程式碼如下:

RNBridgeManager.java 中的程式碼

package com.reactnative;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.uimanager.IllegalViewOperationException;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;

public class RNBridgeManager extends ReactContextBaseJavaModule {

    public RNBridgeManager(ReactApplicationContext reactContext) {

        super(reactContext);

    }

//    重寫getName方法宣告Module類名稱,在RN呼叫時用到
    @Override
    public String getName() {
        return "BridgeManager";
    }

//    宣告的方法,外界呼叫
    @ReactMethod
    public void getAppVersion(Callback successCallback) {
        try {
            PackageInfo info = getPackageInfo();
            if(info != null){
                successCallback.invoke(info.versionName);
            }else {
                successCallback.invoke("");
            }
        } catch (IllegalViewOperationException e){

        }
    }

//    獲取 APP 資訊
    private PackageInfo getPackageInfo(){
        PackageManager manager = getReactApplicationContext().getPackageManager();
        PackageInfo info = null;
        try{
            info = manager.getPackageInfo(getReactApplicationContext().getPackageName(),0);
            return info;
        }catch (Exception e){
            e.printStackTrace();
        }finally {

            return info;
        }
    }
}

複製程式碼

RNReactPackage.java 中的程式碼


package com.reactnative;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class RNReactPackage implements ReactPackage {


    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();

//        新增一個安卓原生的activity模組
        modules.add(new RNBridgeManager(reactContext));

        return modules;
    }

}
複製程式碼

然後在 MainApplication.java 中新增剛剛註冊過的包名

@Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new RNReactPackage()
      );
    }
    
複製程式碼

最後,在RN中呼叫

import React, { Component } from `react`;
import { NativeModules } from `react-native`;

export default class Me extends Component {
    constructor(props) {
        super(props);

        this.state = {
            version: ``,
        }
        this.getVerSion();
    }
// 獲取版本號
    getVerSion() {
    NativeModules.BridgeManager.getAppVersion((event) =>{
                this.setState({
                    version:event
                })
            });
          }
             
複製程式碼

注意事項

  • iOS 橋接時,不要漏了 @synthesize bridge = _bridge;
  • Android 橋接時,暴露的方法需在前面加上 @ReactMethod
  • 在實現相關功能方法時,儘量用 Callback 的形式,網上好多文章使用 return 的形式,在開發時有參考過,但未成功
  • iOS 中的 RCT_EXPORT_MODULE(ToolModule) 以及 Android 中 getName 繫結的名稱,即為RN 呼叫的類名
  • Android 橋接記得在 MainApplication 中繫結相應 Package

相關文章