React Native 桥接原生 iOS 以及 Android 获取 APP 版本号

2,666 阅读2分钟

在使用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