在 React Native (RN) 中,JavaScript 可以通过与原生代码(Android 或 iOS)进行交互来调用原生模块。React Native 提供了一个 NativeModules API,用于从 JavaScript 代码中访问原生模块。你可以通过自定义原生模块将 Java/Kotlin 或 Objective-C/Swift 代码暴露给 JavaScript 层,或者使用 React Native 自带的一些原生模块。

1. 使用现有的原生模块

React Native 本身提供了一些原生模块,可以直接通过 JavaScript 调用这些模块,例如:

  • Geolocation:获取设备位置
  • CameraRoll:访问设备图库
  • PushNotification:发送推送通知
  • ToastAndroid:在 Android 上显示原生 Toast 消息

示例:调用现有原生模块(例如 ToastAndroid

import { ToastAndroid } from 'react-native';

// 显示一个 Toast 消息
ToastAndroid.show('Hello from React Native!', ToastAndroid.SHORT);

2. 自定义原生模块

如果需要调用自定义的原生代码,可以创建一个自定义的原生模块。你需要在 Android 和 iOS 中分别编写相应的原生代码,并通过 NativeModules API 进行调用。

步骤:

  1. 在 Android 中创建原生模块(使用 Java/Kotlin)

在 Android 端创建一个原生模块,并暴露给 JavaScript 使用。

  • 创建原生模块(例如 MyCustomModule.java):
package com.yourapp;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class MyCustomModule extends ReactContextBaseJavaModule {

    public MyCustomModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "MyCustomModule"; // 这个名字会用于 JavaScript 端调用
    }

    @ReactMethod
    public void showMessage(String message) {
        // 在 Android 端显示一个 Toast
        android.widget.Toast.makeText(getReactApplicationContext(), message, android.widget.Toast.LENGTH_SHORT).show();
    }
}
  • 将模块注册到 React Native 中(在 MainApplication.java 中):
import com.yourapp.MyCustomModule; // 导入你的模块

@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new MyCustomPackage() // 添加你的模块
    );
}
  1. 在 iOS 中创建原生模块(使用 Objective-C/Swift)
  • 创建原生模块(例如 MyCustomModule.m):
#import <React/RCTBridgeModule.h>

@interface MyCustomModule : NSObject <RCTBridgeModule>
@end

@implementation MyCustomModule

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(showMessage:(NSString *)message)
{
  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Message"
                                                                 message:message
                                                          preferredStyle:UIAlertControllerStyleAlert];
  UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
  [alert addAction:action];
  UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
  [rootViewController presentViewController:alert animated:YES completion:nil];
}

@end
  • 将模块注册到 React Native 中(在 AppDelegate.m 中):
#import "MyCustomModule.h" // 导入你的模块

// 在 `didFinishLaunchingWithOptions` 方法中注册模块
[RCTBridgeModule registerModule:[MyCustomModule class]];
  1. 通过 JavaScript 调用原生模块

在 JavaScript 代码中使用 NativeModules 来访问你创建的原生模块。

import { NativeModules } from 'react-native';

const { MyCustomModule } = NativeModules;

// 调用原生方法
MyCustomModule.showMessage('Hello from JavaScript!');

3. 传递数据和回调

在原生模块中,除了简单的方法调用,还可以传递数据或使用回调来异步处理数据。

传递参数和使用回调:

Android(Java):

@ReactMethod
public void showMessage(String message, Callback successCallback) {
    // 显示消息
    android.widget.Toast.makeText(getReactApplicationContext(), message, android.widget.Toast.LENGTH_SHORT).show();
    // 调用回调
    successCallback.invoke("Message displayed successfully");
}

iOS (Objective-C):

RCT_EXPORT_METHOD(showMessage:(NSString *)message callback:(RCTResponseSenderBlock)callback)
{
  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Message"
                                                                 message:message
                                                          preferredStyle:UIAlertControllerStyleAlert];
  UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
  [alert addAction:action];
  UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
  [rootViewController presentViewController:alert animated:YES completion:nil];

  // 调用回调
  callback(@[@"Message displayed successfully"]);
}

JavaScript:

MyCustomModule.showMessage('Hello from JavaScript!', (message) => {
  console.log(message); // "Message displayed successfully"
});

总结

  1. 调用现有原生模块:通过 React Native 自带的 API(如 ToastAndroidGeolocation 等)直接访问。
  2. 创建自定义原生模块:在 Android 和 iOS 端分别编写原生代码,并通过 NativeModules 在 JavaScript 中进行调用。