React Native蓝牙串口通信神器:React Native Bluetooth Serial详解
本文从原理、环境配置、核心 API、代码示例、图解等多个维度进行详尽说明,帮助你快速上手 React Native + 蓝牙串口通信开发。
目录
概述
在许多 IoT 场景中,蓝牙串口(Bluetooth Serial Port Profile, SPP)是最常见的无线数据传输方式之一。尤其是当你需要在手机端与 Arduino、Raspberry Pi、各种自制蓝牙模块(如 HC-05/HC-06)等设备通信时,蓝牙串口通信显得尤为重要。
React Native 社区中,有一个叫做 react-native-bluetooth-serial-next
(常简称为 “React Native Bluetooth Serial”)的第三方库,可以帮助我们在 React Native 应用中快速实现蓝牙 SPP 的扫描、连接、收发数据、断开等功能。它对 Android/iOS 都提供了比较完整的封装,并且支持事件回调,非常适合初学者和中小型项目使用。
本文将从最基础的安装开始,一步步带你了解整个流程,并且附上大量代码示例与图解,帮助你快速上手。
环境准备
React Native 环境
- Node.js (建议 v14 及以上)
- React Native CLI (若已安装,可跳过)
- Android Studio / Xcode(根据你做 Android 或 iOS)
目标设备
- 一台具备蓝牙功能的手机(Android 或 iOS)
- 一块支持 SPP 的蓝牙模块(如 HC-05 / HC-06)
- Arduino、树莓派或其他控制板(本文以 HC-05 + Arduino UNO 为示例)
说明: 文中示例代码基于 React Native 0.70+,在 Android 10+ 与 iOS 13+ 上测试通过。
安装与配置
首先,进入你的项目根目录,执行以下命令安装 react-native-bluetooth-serial-next
:
# 使用 npm
npm install react-native-bluetooth-serial-next --save
# 或使用 yarn
yarn add react-native-bluetooth-serial-next
安装完成后,进入 iOS 目录执行 CocoaPods 安装:
cd ios
pod install
cd ..
Tip: 如果你使用了 React Native 0.60 以上(自动链接),上述安装完成后,通常不需要手动链接(react-native link ...
)。如果你遇到链接问题,请参考官方文档自行调整。
原理与整体架构图解
在使用蓝牙串口通信时,整体流程如下:
+---------------------+ +-----------------------+ +----------------------+
| React Native App | <--> | 手机内置蓝牙适配器(BLE/Classic) | <--> | HC-05蓝牙模块(SPP) |
+---------------------+ +-----------------------+ +----------------------+
|
|
v
+----------------------+
| Arduino 控制器 |
+----------------------+
- React Native App:我们通过
react-native-bluetooth-serial-next
调用原生蓝牙 API(Android/ iOS),进行扫描、配对、连接,以及收发数据。 - 手机蓝牙适配器:基于 Classic Bluetooth SPP 协议,它将手机的串口数据转换成射频进行传输。(注意:React Native Bluetooth Serial 默认使用 Classic SPP,非 BLE)
- HC-05 蓝牙模块:通过串口(UART)与 Arduino 等控制器连接,充当蓝牙接收端,接受手机发送的指令或返回传感器数据。
- Arduino / 控制器:通过串口读取或发送数据,进行逻辑处理(如控制电机、读取温度、灯光控制等)。
下面用更直观的流程图来展示主要步骤(扫描→配对→连接→收发→断开):
┌───────────────────────────────────────────────────────────────────┐
│ │
│ [1] 应用启动 -> 初始化库 -> 订阅事件 │
│ │ │
│ ▼ │
│ [2] 开始扫描附近蓝牙设备(Classic) │
│ │ │
│ ▼ │
│ [3] 扫描结果列表:显示 HC-05 / HC-06 等设备 │
│ │ │
│ ▼ │
│ [4] 用户点击 “连接”:触发 connectToDevice(UUID) │
│ │ │
│ ▼ │
│ [5] 与 HC-05 建立 RFCOMM 连接(SPP) │
│ │ │
│ ▼ │
│ [6] 发送/接收串口数据 │
│ - write(data) -> 手机蓝牙 -> HC-05 -> Arduino │
│ - 监听 dataReceived 事件 -> 获取 HC-05 返回数据 │
│ │ │
│ ▼ │
│ [7] 用户点击 “断开”:disconnect() │
│ │
└───────────────────────────────────────────────────────────────────┘
权限设置
Android 权限
AndroidManifest.xml:在项目
android/app/src/main/AndroidManifest.xml
中添加以下权限(<manifest>
节点下):<!-- 蓝牙基础权限 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- Android 12+ 需要额外动态权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <!-- 定位权限:部分 Android 版本扫描蓝牙需要定位授权 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
动态申请:在运行时,需要向用户申请定位权限(Android 6.0+)以及 Android 12+ 的蓝牙权限。可以使用 React Native 自带的
PermissionsAndroid
:import { PermissionsAndroid, Platform } from 'react-native'; async function requestAndroidPermissions() { if (Platform.OS !== 'android') return true; const permissions = []; // Android 12+ 分别申请 if (Platform.constants.Release >= '12') { permissions.push(PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN); permissions.push(PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT); permissions.push(PermissionsAndroid.PERMISSIONS.BLUETOOTH_ADVERTISE); } // 定位权限(扫描蓝牙) permissions.push(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION); try { const granted = await PermissionsAndroid.requestMultiple(permissions); // 检查是否都被授予 const allGranted = Object.values(granted).every(status => status === PermissionsAndroid.RESULTS.GRANTED); return allGranted; } catch (err) { console.warn('权限申请失败', err); return false; } }
iOS 权限
在 ios/YourProject/Info.plist
中,添加如下键值:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>应用需要使用蓝牙来连接设备并进行串口通信。</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>应用需要访问蓝牙外设来发送和接收数据。</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>扫描附近蓝牙设备需要定位权限。</string>
注意: iOS 13+ 要求NSBluetoothAlwaysUsageDescription
,并且如果要做蓝牙扫描,还需要NSLocationWhenInUseUsageDescription
或NSLocationAlwaysUsageDescription
。
核心 API 详解
以下示例基于 react-native-bluetooth-serial-next
,在代码里我们一般这样引用:
import RNBluetoothSerial from 'react-native-bluetooth-serial-next';
1. 初始化与事件订阅
- 初始化库
在 App 启动时,调用RNBluetoothSerial.initialize()
进行初始化。通常可以放在最顶层组件的useEffect
中。 订阅事件
react-native-bluetooth-serial-next
提供了多个事件回调,例如:bluetoothEnabled
:蓝牙已打开bluetoothDisabled
:蓝牙已关闭deviceConnected
:成功连接到设备deviceDisconnected
:设备断开dataReceived
:收到串口数据error
:错误回调
import React, { useEffect, useState } from 'react'; import { NativeEventEmitter, Platform } from 'react-native'; import RNBluetoothSerial from 'react-native-bluetooth-serial-next'; export default function useBluetoothInit() { const [enabled, setEnabled] = useState(false); const bluetoothEmitter = new NativeEventEmitter(RNBluetoothSerial); useEffect(() => { // 初始化 RNBluetoothSerial.initialize() .then(result => { // result = { isEnabled: boolean } setEnabled(result.isEnabled); }) .catch(err => console.error('初始化失败', err)); // 订阅蓝牙开关事件 const subEnabled = bluetoothEmitter.addListener('bluetoothEnabled', () => { console.log('蓝牙已打开'); setEnabled(true); }); const subDisabled = bluetoothEmitter.addListener('bluetoothDisabled', () => { console.log('蓝牙已关闭'); setEnabled(false); }); // 订阅数据接收 const subData = bluetoothEmitter.addListener('dataReceived', ({ data, device }) => { console.log('收到数据:', data, '来自:', device.id); }); return () => { subEnabled.remove(); subDisabled.remove(); subData.remove(); }; }, []); return enabled; }
2. 扫描设备
调用 RNBluetoothSerial.startScanning()
开始扫描,扫描时会收到 deviceFound
事件。也可以直接使用返回值:
async function scanDevices() {
try {
// 开始扫描,持续时间默认 15 秒
const devices = await RNBluetoothSerial.startScanning({});
// devices: Array<{ id: string, name: string }>
console.log('扫描到设备列表:', devices);
return devices;
} catch (err) {
console.error('扫描失败', err);
return [];
}
}
参数说明:
- 可以传递
{ seconds: number }
指定扫描时长,单位为秒,默认为 15 秒。
- 可以传递
事件回调:
bluetoothEmitter.addListener('deviceFound', device => { // device 示例:{ id: '00:11:22:33:44:55', name: 'HC-05' } console.log('发现新设备:', device); });
3. 连接设备
扫描到设备后,用户选择要连接的设备(通常根据 id
或者 name
),调用 connect
方法进行连接:
async function connectToDevice(deviceId) {
try {
const connected = await RNBluetoothSerial.connect(deviceId);
if (connected) {
console.log('已连接到设备:', deviceId);
return true;
} else {
console.warn('连接失败:', deviceId);
return false;
}
} catch (err) {
console.error('连接异常:', err);
return false;
}
}
- 自动重连
如果需要连接后自动重连,可以在deviceDisconnected
事件中逻辑判断后再次调用connectToDevice
。 查看已配对设备
如果想跳过扫描,直接获取手机之前已经配对过的设备,也可以调用:const paired = await RNBluetoothSerial.list(); console.log('已配对设备:', paired);
paired
的数据结构同扫描到的设备:[{ id: string, name: string }]
。
4. 发送数据
连接成功后,就可以调用 write
或者 writeToDevice
将数据写入对端串口。
async function sendData(text) {
try {
// 默认发送字符串,底层会转成 bytes 并通过 RFCOMM 发送
await RNBluetoothSerial.write(text);
console.log('发送成功:', text);
} catch (err) {
console.error('发送失败:', err);
}
}
写入示例:
// 发送 “LED_ON\n” 给 HC-05 模块 sendData('LED_ON\n');
- 写入 Buffer
如果你想发送二进制数据,也可以传入 base64 字符串或字节数组,这里我们一般直接发 ASCII 即可。
5. 接收数据
5.1 通过事件监听
在前面初始化时,我们已经订阅了 dataReceived
事件,当设备端通过串口发送数据时,该回调会触发:
bluetoothEmitter.addListener('dataReceived', ({ data, device }) => {
// data 为字符串,通常包含 \r\n 等换行符
console.log(`从 ${device.id} 收到:`, data);
// 你可以根据业务需求进行解析,例如:
// const parsed = data.trim().split(',');
// console.log('解析后的数组:', parsed);
});
5.2 主动读取缓存
如果你不想使用事件,也可以主动调用 read
或 readFromDevice
,读取设备端发来的缓存数据(不过推荐使用事件):
async function readData() {
try {
const buffer = await RNBluetoothSerial.read();
console.log('主动读取到数据:', buffer);
return buffer;
} catch (err) {
console.warn('读取失败:', err);
return '';
}
}
6. 断开与清理
当不再需要通信时,务必调用 disconnect
来释放资源,并取消相关事件监听,防止内存泄漏。
async function disconnectDevice() {
try {
await RNBluetoothSerial.disconnect();
console.log('已断开连接');
} catch (err) {
console.error('断开失败', err);
}
}
事件取消(在组件卸载时):
useEffect(() => { // 假设在初始化时添加了三个 listener:subEnabled、subDisabled、subData return () => { subEnabled.remove(); subDisabled.remove(); subData.remove(); }; }, []);
完整示例:一个简单的串口控制页面
下面给出一个完整的 React Native 页面示例,包含扫描、展示设备列表、连接、发送指令、接收数据,并用图解的方式标注关键步骤。
1. 项目结构
MyBluetoothApp/
├─ android/
├─ ios/
├─ src/
│ ├─ components/
│ │ └─ DeviceItem.js
│ ├─ screens/
│ │ └─ BluetoothScreen.js
│ └─ App.js
├─ package.json
└─ ...
- App.js:入口文件,导航到
BluetoothScreen
。 - BluetoothScreen.js:实现 Bluetooth 扫描、连接、收发逻辑。
- DeviceItem.js:展示单个设备的列表项。
2. 组件代码
2.1 DeviceItem.js(设备列表项)
// src/components/DeviceItem.js
import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
export default function DeviceItem({ device, onPress }) {
return (
<TouchableOpacity style={styles.itemContainer} onPress={() => onPress(device)}>
<Text style={styles.deviceName}>{device.name || '未知设备'}</Text>
<Text style={styles.deviceId}>{device.id}</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
itemContainer: {
padding: 12,
borderBottomWidth: 0.5,
borderColor: '#ccc',
},
deviceName: {
fontSize: 16,
fontWeight: '500',
},
deviceId: {
fontSize: 12,
color: '#666',
marginTop: 4,
},
});
2.2 BluetoothScreen.js(核心逻辑)
// src/screens/BluetoothScreen.js
import React, { useEffect, useState, useRef } from 'react';
import { View, Text, FlatList, Button, TextInput, TouchableOpacity, StyleSheet, Alert, Platform } from 'react-native';
import RNBluetoothSerial from 'react-native-bluetooth-serial-next';
import { PermissionsAndroid } from 'react-native';
import DeviceItem from '../components/DeviceItem';
export default function BluetoothScreen() {
const [isEnabled, setIsEnabled] = useState(false); // 蓝牙是否打开
const [devices, setDevices] = useState([]); // 扫描到的设备列表
const [connectingId, setConnectingId] = useState(null); // 正在连接的设备 id
const [connectedId, setConnectedId] = useState(null); // 已连接设备 id
const [logData, setLogData] = useState(''); // 接收数据的日志
const [inputText, setInputText] = useState(''); // 要发送的数据
const bluetoothEmitter = useRef(new RNBluetoothSerial.BluetoothEventEmitter()).current;
// 1. 初始化及订阅
useEffect(() => {
async function init() {
// 申请 Android 权限
if (Platform.OS === 'android') {
const granted = await requestAndroidPermissions();
if (!granted) {
Alert.alert('权限不足', '缺少蓝牙或定位权限,无法进行扫描。');
return;
}
}
// 初始化蓝牙
try {
const result = await RNBluetoothSerial.initialize();
setIsEnabled(result.isEnabled);
} catch (err) {
console.error('初始化异常:', err);
}
// 订阅蓝牙开关事件
bluetoothEmitter.addListener('bluetoothEnabled', () => {
setIsEnabled(true);
});
bluetoothEmitter.addListener('bluetoothDisabled', () => {
setIsEnabled(false);
});
// 订阅连接事件
bluetoothEmitter.addListener('deviceConnected', ({ device }) => {
setConnectedId(device.id);
setConnectingId(null);
Alert.alert('连接成功', `已连接:${device.name}`);
});
bluetoothEmitter.addListener('deviceDisconnected', ({ device }) => {
if (device.id === connectedId) {
setConnectedId(null);
Alert.alert('断开连接', `设备 ${device.name} 已断开`);
}
});
// 订阅接收数据
bluetoothEmitter.addListener('dataReceived', ({ data, device }) => {
setLogData(prev => prev + `\n[${device.name || device.id}] ${data}`);
});
}
init();
return () => {
// 注销事件监听
bluetoothEmitter.removeAllListeners('bluetoothEnabled');
bluetoothEmitter.removeAllListeners('bluetoothDisabled');
bluetoothEmitter.removeAllListeners('deviceConnected');
bluetoothEmitter.removeAllListeners('deviceDisconnected');
bluetoothEmitter.removeAllListeners('dataReceived');
};
}, []);
// 2. 扫描设备
const scanDevices = async () => {
try {
setDevices([]); // 清空旧列表
const list = await RNBluetoothSerial.startScanning({ seconds: 8 });
setDevices(list);
} catch (err) {
console.error('扫描失败:', err);
}
};
// 3. 连接设备
const connectDevice = async (device) => {
setConnectingId(device.id);
try {
const ok = await RNBluetoothSerial.connect(device.id);
if (!ok) {
setConnectingId(null);
Alert.alert('连接失败', `无法连接到 ${device.name}`);
}
} catch (err) {
setConnectingId(null);
console.error('连接异常:', err);
}
};
// 4. 发送数据
const sendData = async () => {
if (!connectedId) {
Alert.alert('未连接', '请先连接设备');
return;
}
try {
await RNBluetoothSerial.write(inputText + '\r\n');
setLogData(prev => prev + `\n[我] ${inputText}`);
setInputText('');
} catch (err) {
console.error('发送异常:', err);
}
};
// 5. 断开连接
const disconnectDevice = async () => {
try {
await RNBluetoothSerial.disconnect();
setConnectedId(null);
setLogData(prev => prev + '\n[系统] 已断开连接');
} catch (err) {
console.error('断开失败:', err);
}
};
return (
<View style={styles.container}>
<Text style={styles.title}>React Native 蓝牙串口通信 Demo</Text>
<View style={styles.section}>
<Text>蓝牙状态:{isEnabled ? '已开启' : '未开启'}</Text>
<Button title="扫描设备" onPress={scanDevices} disabled={!isEnabled} />
</View>
<FlatList
style={styles.list}
data={devices}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<DeviceItem
device={item}
onPress={connectDevice}
style={{
backgroundColor: item.id === connectingId ? '#e0f7fa' : '#fff',
}}
/>
)}
ListEmptyComponent={() => <Text style={styles.emptyText}>暂无扫描到设备</Text>}
/>
{connectedId && (
<View style={styles.section}>
<Text>已连接:{connectedId}</Text>
<TextInput
style={styles.input}
placeholder="请输入要发送的串口数据"
value={inputText}
onChangeText={setInputText}
/>
<Button title="发送数据" onPress={sendData} />
<View style={{ height: 10 }} />
<Button title="断开连接" color="#e53935" onPress={disconnectDevice} />
</View>
)}
<View style={styles.logContainer}>
<Text style={styles.logTitle}>通信日志:</Text>
<Text style={styles.logText}>{logData}</Text>
</View>
</View>
);
}
// Android 动态申请权限
async function requestAndroidPermissions() {
const permissions = [];
if (Platform.Version >= 31) {
permissions.push(PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN);
permissions.push(PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT);
permissions.push(PermissionsAndroid.PERMISSIONS.BLUETOOTH_ADVERTISE);
}
permissions.push(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
try {
const granted = await PermissionsAndroid.requestMultiple(permissions);
return Object.values(granted).every(status => status === PermissionsAndroid.RESULTS.GRANTED);
} catch (err) {
console.warn('权限申请异常:', err);
return false;
}
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 12, backgroundColor: '#fafafa' },
title: { fontSize: 20, fontWeight: '600', marginBottom: 12 },
section: { marginVertical: 8 },
list: { flex: 1, marginVertical: 8, borderWidth: 0.5, borderColor: '#ddd', borderRadius: 6 },
emptyText: { textAlign: 'center', color: '#999', padding: 20 },
input: {
borderWidth: 0.8,
borderColor: '#ccc',
borderRadius: 4,
paddingHorizontal: 8,
paddingVertical: 4,
marginVertical: 8,
},
logContainer: {
flex: 1,
marginTop: 12,
padding: 8,
borderWidth: 0.5,
borderColor: '#ccc',
borderRadius: 4,
backgroundColor: '#fff',
},
logTitle: { fontWeight: '500', marginBottom: 4 },
logText: { fontSize: 12, color: '#333' },
});
2.3 App.js(简单导航或直接渲染)
// src/App.js
import React from 'react';
import BluetoothScreen from './screens/BluetoothScreen';
export default function App() {
return <BluetoothScreen />;
}
图解说明
初始化与事件订阅流程
┌──────────────────────────┐ │ App 启动 │ │ → requestAndroidPermissions() │ │ → RNBluetoothSerial.initialize() │ └─────────────┬────────────┘ │ ▼ 注册事件监听:bluetoothEnabled / bluetoothDisabled / deviceConnected / dataReceived…
扫描 & 列表展示
用户点击 “扫描设备” ↓ RNBluetoothSerial.startScanning({seconds:8}) ↓ onSuccess 返回设备数组,更新 state → FlatList 渲染列表 ↓ 用户可点击某项设备,触发 connectDevice(item)
连接 & 数据交换
用户点击设备 → connectToDevice ↓ RNBluetoothSerial.connect(deviceId) → 建立 RFCOMM 连接 ↓ 订阅 deviceConnected 事件 → 更新 connectedId ↓ // 发送数据 用户输入文本 → 点击 “发送数据” → write(input + '\r\n') ↓ HC-05 通过串口(UART)收到数据 → Arduino 处理 → 可能通过 UART 回复 ↓ HC-05 将回复通过蓝牙 SPP 发送回手机 → 触发 dataReceived 事件 → 更新 logData
断开连接
用户点击 “断开连接” ↓ RNBluetoothSerial.disconnect() ↓ 触发 deviceDisconnected 事件 → 清空 connectedId
以上图解帮助你对蓝牙串口通信的时序与流程有更直观的认识。
注意事项与常见问题
Classic 蓝牙 vs BLE
- 本库使用 Classic Bluetooth SPP(串口协议),并非 BLE(Bluetooth Low Energy)。BLE 需要另用
react-native-ble-plx
等库。 - SPP 可以直接当作串口,方便 Arduino、STM32 等微控制器通信。
- 本库使用 Classic Bluetooth SPP(串口协议),并非 BLE(Bluetooth Low Energy)。BLE 需要另用
蓝牙名称可能为
null
/ 空字符串- 某些设备出于隐私或低功耗考虑,名称可能为空,只能通过 MAC 地址判断。建议在界面上同时展示
id
(MAC)与name
,并加以提示。
- 某些设备出于隐私或低功耗考虑,名称可能为空,只能通过 MAC 地址判断。建议在界面上同时展示
Android 12+ 权限问题
- Android 12(API 31)之后,扫描 需要
BLUETOOTH_SCAN
,连接 需要BLUETOOTH_CONNECT
。同时,扫描通常还需要定位权限。 - 如需在后台扫描,可能还需要
ACCESS_BACKGROUND_LOCATION
。
- Android 12(API 31)之后,扫描 需要
iOS 系统弹窗
- 如果缺少
Info.plist
中对应的键,iOS 会直接导致崩溃或拒绝蓝牙请求。务必检查是否填写了NSBluetoothAlwaysUsageDescription
、NSLocationWhenInUseUsageDescription
等项。
- 如果缺少
连接超时、重连逻辑
- 某些设备在配对后并非立刻能够连接成功,如果连接失败,建议在
catch
中加上重试。 - 也可在
deviceDisconnected
回调中,根据具体需求自动重连(谨慎使用,避免死循环重连)。
- 某些设备在配对后并非立刻能够连接成功,如果连接失败,建议在
数据格式与换行
- 大多数串口设备以
\r\n
作为一条指令或数据结束符,发送时建议在末尾加上换行符。也可以在initialize()
时传递 分隔符 让库自动做数据分片。 - 如果接收乱码,请确认手机蓝牙与设备蓝牙波特率、数据位、停止位、校验位等是否匹配(通常 HC-05 默认 9600、8N1)。
- 大多数串口设备以
调试方式
- 串口调试助手:在 Windows 或 Mac 上使用串口助手(如 SecureCRT、PuTTY、CoolTerm 等)先调试 HC-05 与 Arduino,确保指令逻辑正常。
- 日志打印:React Native 层面可开启
adb logcat
(Android)或 Xcode 控制台,定位蓝牙模块的连接/断开/异常。
总结
本文从安装、配置、原理到完整代码示例,详细讲解了如何使用 react-native-bluetooth-serial-next
(也称 React Native Bluetooth Serial)实现蓝牙串口通信。核心流程包括:
- 初始化:申请权限 → 初始化库 → 订阅蓝牙事件
- 扫描:调用
startScanning
,获取设备列表 - 连接:调用
connect
,建立 RFCOMM 连接 - 收发:通过
write
、dataReceived
完成数据交换 - 断开:调用
disconnect
,释放资源
通过以上步骤,你可以在 React Native 应用中快速搭建一个蓝牙串口调试或控制界面。例如,控制 Arduino 上的 LED 开关、读取传感器数据、远程控制舵机等。
扩展思考:
- 如果项目后续对低功耗、广播查询等需求增多,可考虑使用 BLE 并结合
react-native-ble-plx
。- 如果需要在后台持续扫描或连接,需要结合原生模块做更多权限及生命周期管理。
希望这篇详细的图文+代码示例文章,能帮助你更快速地上手 React Native 蓝牙串口通信,打造自己的“蓝牙神器”!
评论已关闭