【大前端】React Native 调用 Android、iOS 原生能力封装


📖 React Native 调用 Android、iOS 原生能力封装

1. 原理

React Native 的 核心思想

  • JS 层(React 代码)不能直接调用 Android/iOS 的 API。

  • RN 提供了 Native Module 机制

    • Android :Java/Kotlin → 继承 ReactContextBaseJavaModule,通过 @ReactMethod 暴露方法。
    • iOS :Objective-C/Swift → 使用 RCT_EXPORT_MODULERCT_EXPORT_METHOD 暴露方法。
  • JS 调用时通过 NativeModules 拿到对应的模块,再调用方法。

  • 双向通信

    • JS → 原生(方法调用)
    • 原生 → JS(事件通知 / 回调 Promise)

2. Android 封装原生能力

(1)新建原生 Module

java 复制代码
// MyNativeModule.java
package com.myapp;

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

public class MyNativeModule extends ReactContextBaseJavaModule {
    MyNativeModule(ReactApplicationContext context) {
        super(context);
    }

    @Override
    public String getName() {
        return "MyNative"; // JS 调用时用的名字
    }

    // 示例:获取电池电量
    @ReactMethod
    public void getBatteryLevel(Promise promise) {
        try {
            int battery = 80; // 假设写死,实际可用系统 API 获取
            promise.resolve(battery);
        } catch (Exception e) {
            promise.reject("ERROR", e);
        }
    }
}

(2)注册 Module

java 复制代码
// MyPackage.java
package com.myapp;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MyPackage implements ReactPackage {
  @Override
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();
    modules.add(new MyNativeModule(reactContext));
    return modules;
  }

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }
}

MainApplication.java 里注册:

java 复制代码
packages.add(new MyPackage());

3. iOS 封装原生能力

(1)Objective-C 示例

objc 复制代码
// MyNativeModule.m
#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_MODULE(MyNative, NSObject)

RCT_EXTERN_METHOD(getBatteryLevel:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)

@end

(2)Swift 示例

swift 复制代码
@objc(MyNative)
class MyNative: NSObject {
  @objc
  func getBatteryLevel(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
    let battery = 80 // 假设写死
    resolve(battery)
  }
}

4. JS 调用

tsx 复制代码
import { NativeModules } from 'react-native';
const { MyNative } = NativeModules;

async function checkBattery() {
  try {
    const level = await MyNative.getBatteryLevel();
    console.log("电池电量:", level);
  } catch (e) {
    console.error(e);
  }
}

5. 原生 → JS 的事件通知

有些能力(如推送、传感器数据)需要原生主动回调 JS。

  • Android :使用 DeviceEventManagerModule
java 复制代码
WritableMap params = Arguments.createMap();
params.putString("event", "BatteryLow");
reactContext
  .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
  .emit("BatteryEvent", params);
  • iOS :使用 RCTEventEmitter
objc 复制代码
[self sendEventWithName:@"BatteryEvent" body:@{@"event": @"BatteryLow"}];
  • JS 监听
tsx 复制代码
import { NativeEventEmitter, NativeModules } from 'react-native';

const eventEmitter = new NativeEventEmitter(NativeModules.MyNative);
eventEmitter.addListener('BatteryEvent', (event) => {
  console.log(event);
});

6. 最佳实践

  1. 模块化封装

    • 每个功能一个 Native Module,按业务拆分。
    • 统一放在 /native-modules/ 目录下,JS 层再封装一层 API。
  2. 跨平台统一接口

    • 在 JS 层写一个 Battery.ts,内部判断 Platform.OS 调用 Android/iOS 实现。
  3. 避免直接调用 NativeModules

    • 封装成业务方法,例如:

      tsx 复制代码
      export async function getBatteryLevel(): Promise<number> {
        return await NativeModules.MyNative.getBatteryLevel();
      }
  4. 新架构 TurboModules(进阶):

    • 使用 JSI 直接绑定 C++ → JS 方法,无需 Bridge。
    • 更高性能(避免 JSON 序列化)。

📌 总结:

RN 调用原生能力 = JS ↔ Native Module ↔ Android/iOS API

  • JS 调用 Native:NativeModules.MyNative.xxx()
  • Native 调用 JS:事件/回调/Promise
  • 封装要点:统一接口、模块化、尽量隐藏平台差异

相关推荐
老华带你飞10 分钟前
商城推荐系统|基于SprinBoot+vue的商城推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·毕设·商城推荐系统
JS.Huang12 分钟前
【JavaScript】Pointer Events 与移动端交互
前端·javascript
一 乐14 分钟前
物业管理系统|小区物业管理|基于SprinBoot+vue的小区物业管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端
H_HX12618 分钟前
vue3 - 图片放大镜效果实现
前端·vue.js·vue3·vueuse·图片放大镜
介一安全1 小时前
【Frida Android】基础篇15(完):Frida-Trace 基础应用——JNI 函数 Hook
android·网络安全·ida·逆向·frida
吞掉星星的鲸鱼1 小时前
android studio创建使用开发打包教程
android·ide·android studio
陈老师还在写代码1 小时前
android studio 签名打包教程
android·ide·android studio
csj501 小时前
android studio设置
android
hifhf1 小时前
Android Studio gradle下载失败报错
android·ide·android studio
陈老师还在写代码1 小时前
android studio,java 语言。新建了项目,在哪儿设置 app 的名字和 logo。
android·java·android studio