React Native集成原生代码

尽管React Native官方提供了许多原生api简化我们的开发流程,但是在实际开发过程中,往往需要我们自行封装原生代码供RN层进行调用,本文将分Android和iOS平台简单介绍具体流程。

Android:

假如我们想要原生提供一个方法,将JS抛出的异常写入到本地(这有助于我们在release包中迅速的定位问题的原因),首先我们需要创建一个继承自ReactContextBaseJavaModule类的工具类,作为导出原生方法的入口:

ToolModule.java

package com.smarthome.modules;

import android.util.Log;

import androidx.annotation.NonNull;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.smarthome.utils.FileUtils;

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class ToolModule extends ReactContextBaseJavaModule {
    private ReactContext mContext;
    private final String TAG = "ToolModule";

    public ToolModule(ReactApplicationContext reactContext) {
        super(reactContext);
        mContext = reactContext;
    }

    @Override
    public String getName() {
        return "ToolModule";
    }

    @ReactMethod
    public void saveJSExceptionsToStorage(String exceptionText) {
        Log.d(TAG, "exceptionText: " + exceptionText);
        String externalFilePath = FileUtils.getExternalFileDir().getPath();
        String targetDir = externalFilePath + File.separator + "jsExceptionLogs";
        File log = new File(targetDir);
        if (log.exists() ||
                (!log.exists() && log.mkdir())) {
            StringBuilder targetFilePath = new StringBuilder();
            Date now = new Date();
            DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.getDefault());
            targetFilePath.append(targetDir).append(File.separator).append("log_").append(dateFormat.format(now)).append(".txt");
            File targetFile = new File(targetFilePath.toString());
            FileUtils.writeTextToFiles(targetFile, exceptionText);
        }
    }
}

然后,我们需要再创建一个类继承自ReactPackage,并将工具类ToolModule实例化,添加到createNativeModules方法返回的List<NativeModule>集合中:

package com.smarthome.modules;


import androidx.annotation.NonNull;

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.Arrays;
import java.util.List;

public class CustomPackage implements ReactPackage {
    @Override
    @NonNull
    public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList();
    }

    @Override
    @NonNull
    public List<NativeModule> createNativeModules(
           @NonNull ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new ToolModule(reactContext));
        return modules;
    }
}

接着在MainApplication.java文件中,把CustomPackage类的实例添加到packages集合中即可:

packages.add(new CustomPackage());

最后我们只需要在RN代码中调用NativeModules.ToolModule.saveJSExceptionsToStorage,就可以调用原生层定义的函数。

 

iOS:

假设我们需要获取iOS部分系统信息,我们同样将方法定义在ToolModule中,先要分别创建对应的头文件和实现文件:

ToolModule.h

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

@interface ToolModule: RCTEventEmitter <RCTBridgeModule>
  
@end

ToolModule类需要继承RCTEventEmitter类(原生层发送事件通知RN层)并遵循RCTBridgeModule协议(RN层可以调用原生层方法)。然后是实现文件:

ToolModule.m

#import "ToolModule.h"

@implementation ToolModule
static id _instace;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    _instace = [super allocWithZone:zone];
  });
  return _instace;
}

+ (BOOL)requiresMainQueueSetup {
  return YES;
}

RCT_EXPORT_MODULE();

#pragma mark - 获取iOS系统信息
RCT_EXPORT_METHOD(equipmentInfo:(RCTPromiseResolveBlock)resolve
                  reject:(__unused RCTPromiseRejectBlock)reject){
  //获取系统语言
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  NSArray *languages = [defaults objectForKey:@"AppleLanguages"];
  NSString *currentLanguage = [languages objectAtIndex:0];
  
  //获取系统版本号
  NSString *sysVersion = [[UIDevice currentDevice] systemVersion];
  
  //获取手机型号
  NSString* phoneModel = [[UIDevice currentDevice] model];
  
  //获取手机设备名
  NSString* deviceName = [[UIDevice currentDevice] systemName];
  
  NSDictionary *dic = @{@"language":currentLanguage,
                        @"sysVersion":sysVersion,
                        @"phoneModel":phoneModel,
                        @"deviceName":deviceName,
                        };
  resolve(dic);
}

@end

上面的代码可以看到,我们只需要在实现文件中调用RCT_EXPORT_MODULE();,并将需要导出给RN使用的方法通过RCT_EXPORT_MODULE()宏注册成原生模块。这里的equipmentInfo方法返回的是一个Promise对象,成功决议的Promise中包含着我们需要的字典形式的iOS系统信息。

同样,在RN代码中,我们只需要通过NativeModules.ToolModule.equipmentInfo().then(dic => {});的形式获取原生iOS层传递过来的数据。

 

通过上面的例子,我们可以发现RN集成原生的能力是非常强的。这里介绍的仅仅只是RN主动调用原生提供的方法。实际上我们还可以通过接收原生事件的形式来与原生进行通信,甚至是自行封装原生视图组件供RN层使用,这将在我之后的博客中介绍。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
React Native提供了一个称为Native Modules的机制,允许您在React Native应用程序中使用原生代码。因此,您可以使用Java或Kotlin编写原生Android代码,并将其与React Native应用程序集成。以下是一些步骤: 1.创建一个新的Android库项目。 2.在您的React Native项目中创建一个新的Native Module。 3.将您的原生代码添加到Android库项目中。 4.编写Java或Kotlin代码来公开原生方法。 5.在React Native Native Module中使用这些方法。 6.构建并运行您的React Native应用程序。 这里是一个简单的例子,说明如何在React Native应用程序中使用原生Android模块: 1.创建一个新的Android库项目 在Android Studio中,选择“File” > “New” > “New Module”。然后选择“Android Library”并按照向导中的说明创建一个新的Android库项目。 2.在您的React Native项目中创建一个新的Native Module 在React Native项目的根目录下,运行以下命令: ``` react-native create-library MyNativeModule ``` 此命令将创建一个名为MyNativeModule的新目录。在此目录中,您可以添加一个名为MyNativeModule.java的文件。 3.将您的原生代码添加到Android库项目中 将您的原生代码复制到Android库项目中的src/main/java目录中。 4.编写Java或Kotlin代码来公开原生方法 在您的Java或Kotlin类中,使用@ReactMethod注释来标记要公开给React Native原生方法。例如: ``` @ReactMethod public void showToast(String message) { Toast.makeText(getReactApplicationContext(), message, Toast.LENGTH_SHORT).show(); } ``` 5.在React Native Native Module中使用这些方法 在您的React Native应用程序中,导入MyNativeModule并调用其方法。例如: ``` import { NativeModules } from 'react-native'; const { MyNativeModule } = NativeModules; MyNativeModule.showToast('Hello, world!'); ``` 6.构建并运行您的React Native应用程序 在React Native应用程序的根目录中,运行以下命令以构建并运行您的应用程序: ``` react-native run-android ``` 这样,您就可以在React Native应用程序中使用原生Android模块了!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值