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