推荐用于学习RN原生模块开发的开源库—react-native-ble-manager

本文介绍了RN原生模块开发的重要性,通过分析react-native-ble-manager库,展示了如何进行JS与原生代码的交互,包括Callback的使用和EventEmitter事件通信机制。同时,文章提供了阅读和理解原生模块代码的建议,强调了分层架构和角色视角在理解中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如题RN的原生模块/Native Modules的开发是一项很重要的技能,但RN官网的示例又比较简单,然后最近我接触与使用、还有阅读了react-native-ble-manager的部份源码,发现里边完全包含了一个Native Modules所涉及的知识点/技术点,故特推荐给大家,共同学习与交流
react-native-ble-manager目前有1.8K的star
在这里插入图片描述
如下所示,react-native-ble-manager是RN开发环境下蓝牙低功耗库,用于RN应用下的低功耗蓝牙通讯功能的编程
在这里插入图片描述

react-native-ble-manager的代码结构

代码量不多,如果有原生平台下的蓝牙开发/API有基础的话,阅读起来会更容易些
在这里插入图片描述

于分层思想理解原生模块

Android 原生模块 的指引内容如下
在这里插入图片描述
在RN项目开发过程中,大多数情况下我的业务逻辑、基础库等基本是用JS/TS代码去组织与编写的,但实际我们用的大部份RN第三方面都是一个个原生模块形态的SDK。我们在项目中添加一个原生模块相对于构建一个原生模块形态的SDK要简单些,SDK的话还需要处理构建打包。如下是我于分层架构的思想对原生模块的理解。原生模块顾名思义就是需要依赖与使用到原生平台的API或功能的模块,该模块对于上层业务来说是一个普通的JS模块,故原生模块是实际上是存在两大子模块,一个是用JS模块,另一个是平台层模块,JS模块直接服务上层JS业务模块的,即称之为接口模块,然后平台层模块是内部的实现模块,使用平台层语言直接使用平台层的功能特性。那原生模块的JS代码跟平台层代码是如何通讯/交互的呢?这种场景是需要引入一个胶水层来处理,但我们不需要想Android jni开发那样去花大量的精力去构建胶水层,原因RN框架已经提供了这个胶水层的功能,所以我就按RN 原生模块开发的规范来构建与编写相关的代码就行了
在这里插入图片描述

从角色视角理解原生模块

在这里插入图片描述

通过react-native-ble-manager去看原生模块

介绍Android平台为主

主要文件

在这里插入图片描述

主要类图

在这里插入图片描述

从scan接口看JS与原生的交互

从JS的scan跟到Java层的scan接口,可以大概了解参数类型的转化,还有JS调用native方法后面回调处理,使用callback的方式
在这里插入图片描述

//js代码调scan,RN框架会帮忙代到并调到对应native层的scan方法,同时调用该方法时会做js数据类型到java数据类型的转换
 bleManager.scan(
        serviceUUIDs,
        seconds,
        allowDuplicates,
        scanningOptions,
        //下面这个就是一个js function对应到java就是一个callback类型
        (error: string | null) => {
          if (error) {
            reject(error);
          } else {
            fulfill();
          }
        }
      );
    });
//如下是java代码,BleManager.java类中scan方法
 @ReactMethod
    public void scan(ReadableArray serviceUUIDs, final int scanSeconds, boolean allowDuplicates, ReadableMap options,
                     Callback callback) {
        Log.d(LOG_TAG, "scan");
        if (getBluetoothAdapter() == null) {
            Log.d(LOG_TAG, "No bluetooth support");
            callback.invoke("No bluetooth support");
            return;
        }
        if (!getBluetoothAdapter().isEnabled()) {
            return;
        }

        synchronized (peripherals) {
            for (Iterator<Map.Entry<String, Peripheral>> iterator = peripherals.entrySet().iterator(); iterator
                    .hasNext(); ) {
                Map.Entry<String, Peripheral> entry = iterator.next();
                if (!(entry.getValue().isConnected() || entry.getValue().isConnecting())) {
                    iterator.remove();
                }
            }
        }

        if (scanManager != null)
            scanManager.scan(serviceUUIDs, scanSeconds, options, callback);
    }

注意观察上面的JS代码中调scan方法的参数,然后再对着下面JS数据类型跟JAVA数据类型的关系去看代码。
特别要重点体会callback跟function的映射,因为callback是native方法回调js时经常用到的方式
在这里插入图片描述
再来看一下native主动向js交互的case,目前是采用EventEmitter机制来交互的。即JS需要注册事件,然后native端发送对应的事件即可。这个事件从Jvmruntime到Js runtime的胶水层RN已经帮忙我们实现了,调用对应的emmiter组件即可
如下是JS端注册事件的代码

const BleManagerModule = NativeModules.BleManager;
const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);
//注删事件ID是一个String,如下面的 BleManagerDiscoverPeripheral,然后我们去native端的代码去搜索BleManagerDiscoverPeripheral
....
 const listeners = [
      bleManagerEmitter.addListener(
        'BleManagerDiscoverPeripheral',
        handleDiscoverPeripheral,
      ),
      bleManagerEmitter.addListener('BleManagerStopScan', handleStopScan),
      bleManagerEmitter.addListener(
        'BleManagerDisconnectPeripheral',
        handleDisconnectedPeripheral,
      ),
      bleManagerEmitter.addListener(
        'BleManagerDidUpdateValueForCharacteristic',
        handleUpdateValueForCharacteristic,
      ),
    ];

//通过BleManagerDiscoverPeripheral看到native的有这样的代码, 
private void onDiscoveredPeripheral(final ScanResult result) {
        .....

        WritableMap map = peripheral.asWritableMap();
        bleManager.sendEvent("BleManagerDiscoverPeripheral", map);
    }

 public void sendEvent(String eventName, @Nullable WritableMap params) {
      getReactApplicationContext().getJSModule(RCTNativeAppEventEmitter.class).emit(eventName, params);
 }

总结

1、native端用RCTNativeAppEventEmitter来发送事件,js端用NativeEventEmitter来注册事件,即达到下层可以主动向上层通讯
2、callback经常用来作native方法的调用结果返回到JS runtime的常规操作,即方法调用与结果返回,一来一回的双向操作。

建议

1、用webstorm打开整个目标,方便阅读js/ts代码
2、用AS打开Android目录,方便阅读java代码
3、用xcode或appcode打开ios目录,方便阅读ios代码

### 关于 `react-native-ble-manager` 的安装、使用教程以及示例代码 #### 安装指南 为了在 React Native 应用程序中集成 `react-native-ble-manager`,需要按照特定步骤操作。首先,在命令行工具中执行如下 npm 命令来安装该库: ```bash npm install --save react-native-ble-manager ``` 对于 iOS 平台的支持,还需通过 CocoaPods 来处理依赖关系;而对于 Android,则要确保已正确设置权限并链接本地模块[^1]。 #### 初始化与配置 完成上述安装之后,需对项目做进一步初始化工作。这涉及到向应用程序注册原生模块,并监听来自蓝牙设备的消息事件。下面是一段 JavaScript 代码片段展示如何实例化 `BleManager` 对象并与之交互[^3]。 ```javascript import { NativeModules, Platform } from 'react-native'; const BleManagerModule = NativeModules.BleManager; let bleManagerEmitter; if (Platform.OS === 'ios') { bleManagerEmitter = new NativeEventEmitter(NativeModules.BleManager); } else if (Platform.OS === 'android') { // For newer versions of RN you may need to use RCTDeviceEventEmitter instead. bleManagerEmitter = new NativeEventEmitter(BleManagerModule); } ``` 这段代码展示了基于不同操作系统平台的选择性逻辑分支,以适配各自环境下的特性差异。 #### 使用教程概览 当一切准备就绪后,开发者可以利用所提供的 API 进行诸如扫描周边可用的 BLE 设备、连接目标外设等一系列操作。具体来说,可以通过调用相应的方法如 `start`, `scan`, 和 `connectToDevice` 等来进行实际的数据交换过程[^4]。 例如,启动 Bluetooth LE 扫描器可按以下方式编码实现: ```javascript await BleManager.start({ showAlert: false }); // Start scanning after a delay so the queue can process the start event first setTimeout(() => { console.log('Scanning...'); manager.scan([], 5, true).then((results) => { console.log('Scan finished'); }).catch(error => { console.error(`Error while scanning ${error}`); }); }, 1000); ``` 此部分提供了基本的操作流程指导,帮助初学者快速上手。 #### 示例代码解析 最后给出一段完整的例子用来说明怎样在一个简单的页面内运用这些功能。这里假设已经完成了前面提到的所有准备工作。 ```jsx import React, { useEffect, useState } from 'react'; import { View, Text, Button, Alert } from 'react-native'; import BleManager from 'react-native-ble-manager'; export default function App() { const [isBluetoothEnabled, setIsBluetoothEnabled] = useState(false); useEffect(() => { BleManager.start({ showAlert: false, }); const subscription = BleManager.onStateChange((state) => { if (state === 'PoweredOn') { setIsBluetoothEnabled(true); } }, true); return () => { subscription.remove(); }; }, []); async function handleStartScanPress() { try { await BleManager.enableBluetooth(); // Ensure bluetooth is enabled on device let devicesFound = []; BleManager.scan([], 5, true).subscribe( (device) => { devicesFound.push(device); console.log(`Discovered Device with ID: ${device.id}`); }, (error) => { console.warn(`Error during scan: ${JSON.stringify(error)}`); } ); } catch (e) { console.error(e.message); } } return ( <View style={{ flex: 1 }}> <Text>Is Bluetooth Enabled? {`${isBluetoothEnabled}`}</Text> <Button title="Start Scanning" onPress={handleStartScanPress}></Button> </View> ); } ``` 以上就是有关 `react-native-ble-manager` 的一些核心知识点介绍及其实践案例分享[^1].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值