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