React Native BLE蓝牙通信 App开发
Posted 拼了命的珍惜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React Native BLE蓝牙通信 App开发相关的知识,希望对你有一定的参考价值。
由于公司项目需要,开发一个基于rn的app与公司蓝牙模块下位机进行通讯。用来扫描并连接可用的外设,然后读取和写入数据。
项目选用的蓝牙库是:react-native-ble-manager,详细安装教程和api文档查看官方文档即可。
app采用react-native+react-native-navigation+typescript+hook状态管理技术栈。
如有疑问可联系我或在下方评论区留言。
项目地址:https://github.com/HY88883/Bluetooth_central
友情提示:如果能帮到你的话,给个star哦,感激不尽~
react-native-ble-manager只适用于BLE蓝牙通信,不适用于经典蓝牙通信,接入前请确保你的设备是BLE(低功耗)蓝牙,以免前功尽弃。
app部分截图如下:
进入首页,扫描附近ble设备,默认扫描5s,可停止扫描。点击下方设备列表中的某一项进行连接。点击上方按钮中的选项可以清空。
可以查看已连接的设备,点击跳转到服务和特征详情页。
可以看到该设备的服务uuid和特征uuid,点击某一个特征,进入对应页面。
这里可以对特征进行操作,显示了当前该特征具备哪些属性,可进行读取、写入操作。
下面展示主要文件:
import React, {FunctionComponent, useContext, useEffect, useLayoutEffect, useRef, useState} from 'react';
import {
View,
Text,
StyleSheet,
Platform,
Permissionsandroid,
Alert,
NativeModules,
NativeEventEmitter, FlatList, TouchableHighlight, Linking, SafeAreaView, TouchableOpacity, ScrollView
} from "react-native";
// import HeaderButtons from "./components/HeaderButtons";
import BleManager from "react-native-ble-manager";
import {Button} from "react-native-paper";
import AntDesign from "react-native-vector-icons/AntDesign";
import {px2dp} from "../utils";
import Ionicons from "react-native-vector-icons/Ionicons";
import Toast from 'teaset/components/Toast/Toast'
import IconFont from "../assets/iconfont";
import {navigate} from "../utils/RootNavigation";
import Overlay from './components/OverlayLoading'
import { Dialog, Portal, Text as PText,List } from 'react-native-paper';
import usePageHeaderTitle from "./components/usePageHeaderTitle";
import HeaderButtons, { Item } from 'react-navigation-header-buttons'
import {DispatchContext, GlobalDataContext} from "../context";
import {ADD_DEVICE, MINUS_DEVICE} from "../reducer";
const BleManagerModule = NativeModules.BleManager;
const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);
interface OwnProps {}
type Props = OwnProps;
const Blutooth: FunctionComponent<Props> = (props) => {
const [isScanning, setIsScanning] = useState(false);
const peripherals = useRef(new Map()).current;
const [list, setList] = useState([]);
const [visible,setVisible]=useState(false)
const {_dispatch}=useContext(DispatchContext)
const {list:deviceList}=useContext(GlobalDataContext)
useEffect(()=>{
const initfn=async ()=>{
try {
const result = await BleManager.start({showAlert: true});
console.log('result====', JSON.stringify(result))
if (!result) {
BleManager.checkState();
bleManagerEmitter.addListener('BleManagerDiscoverPeripheral', handleDiscoverPeripheral);
bleManagerEmitter.addListener('BleManagerStopScan', handleStopScan);
bleManagerEmitter.addListener('BleManagerConnectPeripheral',handleConnectPeripheral);
bleManagerEmitter.addListener('BleManagerDisconnectPeripheral', handleDisconnectedPeripheral);
bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic', handleUpdateValueForCharacteristic);
bleManagerEmitter.addListener("BleManagerDidUpdateState",handleDidUpdateState )
return (() => {
console.log('unmount');
bleManagerEmitter.removeListener('BleManagerDiscoverPeripheral', handleDiscoverPeripheral);
bleManagerEmitter.removeListener('BleManagerStopScan', handleStopScan);
bleManagerEmitter.removeListener('BleManagerDisconnectPeripheral', handleDisconnectedPeripheral);
bleManagerEmitter.removeListener('BleManagerDidUpdateValueForCharacteristic', handleUpdateValueForCharacteristic);
bleManagerEmitter.removeListener("BleManagerDidUpdateState",handleDidUpdateState )
})
} else {
Toast.fail('蓝牙初始化失败,请检查相关设置再重试')
}
}catch (e) {
console.log('e',e)
}
}
initfn()
},[])
const handleDiscoverPeripheral = (peripheral) => {
if (!peripheral.name) {
peripheral.name = '未知设备';
}
peripherals.set(peripheral.id, peripheral);
setList(Array.from(peripherals.values()));
}
const startScan = () => {
console.log('startScan')
if (!isScanning) {
BleManager.scan([], 5, false).then((results) => {
console.log('Scanning...',JSON.stringify(results));
setIsScanning(true);
}).catch(err => {
Toast.fail('扫描出错了')
console.error('err',err);
});
}
}
const stopScan=()=>{
BleManager.stopScan().then(() => {
// Success code
console.log("Scan stopped");
}).catch(err=>{
console.log('err',err)
})
}
const handleStopScan = () => {
console.log('Scan is stopped=============xx====');
setIsScanning(false);
}
const handleDisconnectedPeripheral = (data) => {
console.log('data=========',JSON.stringify(data))
Overlay.removeLoading()
Toast.fail('已断开与 BLE 蓝牙设备的连接')
let peripheral = peripherals.get(data.peripheral);
if (peripheral) {
peripheral.connected = false;
peripherals.set(peripheral.id, peripheral);
setList(Array.from(peripherals.values()));
}
_dispatch({
type:MINUS_DEVICE,
payload:{id:data.peripheral}
})
console.log('Disconnected from ' + data.peripheral);
}
const handleUpdateValueForCharacteristic = (data) => {
console.log('Received data from ' + data.peripheral + ' characteristic ' + data.characteristic, data.value);
}
const onOpenBluetooth = () => {
if (Platform.OS === 'ios') {
Linking.openURL('App-Prefs:root=Bluetooth')
} else {
BleManager.enableBluetooth().catch(() =>{})
}
}
const handleDidUpdateState=args=>{
console.log('handleDidUpdateState',args)
if(args.state==='off'){
Alert.alert(
'蓝牙未开启',
'需要您开启蓝牙才能使用后续功能',
[
{ text: '取消' },
{ text: '开启蓝牙', onPress: onOpenBluetooth }
]
)
// Toast.fail('需要您开启蓝牙才能使用后续功能')
}else if(args.state==='on'){
Toast.success('蓝牙已开启')
}
}
const handleConnectPeripheral=args=>{
Toast.success('已连接到 BLE 蓝牙设备')
console.log('handleConnectPeripheral',args)
}
const testPeripheral = (peripheral) => {
console.log(peripheral)
if (peripheral){
if (peripheral.connected){
BleManager.disconnect(peripheral.id)
}else{
stopScan() // 连接时停止扫描
setTimeout(()=>{
Overlay.displayLoading('正在连接设备...')
BleManager.connect(peripheral.id).then(() => {
let p = peripherals.get(peripheral.id);
console.log('p===',p)
if (p) {
p.connected = true;
peripherals.set(peripheral.id, p);
setList(Array.from(peripherals.values()));
}
Overlay.removeLoading()
setTimeout(()=>{
BleManager.retrieveServices(peripheral.id).then(peripheralData=>{
_dispatch({
type: ADD_DEVICE,
payload: peripheralData
})
Alert.alert('成功连接设备', '需要立即查看该设备详情吗', [
{ text: '下次' },
{ text: '去看看', onPress: () => navigate('Device') }
])
})
},500)
console.log('Connected to ' + peripheral.id);
}).catch((error) => {
console.log('Connection error', error);
});
},500)
}
}
}
const renderItem = (item) => {
const color = item.connected ? 'green' : '#fff';
return (
<TouchableOpacity onPress={() => testPeripheral(item) } activeOpacity={0.7}>
<View style={[styles.row, {backgroundColor: color}]}>
<View>
<Text style={styles.name}>{item.localName||item.name}</Text>
<View style={styles.bView}>
<Text style={styles.btext}>RSSI: {item.rssi}</Text>
<Text style={styles.btext}>{item.id}</Text>
</View>
</View>
<IconFont name={'arrow'} size={px2dp(20)}/>
</View>
</TouchableOpacity>
);
}
const hideDialog=()=>{
setVisible(false)
}
const cleanAllDevices=async()=>{
for(let i=0;i<deviceList.length;i++){
try {
await BleManager.disconnect(deviceList[i].id)
}catch (e) {
}
}
_dispatch({
type:'connectedDevice/cleanAll'
})
setList([])
peripherals.clear()
}
return (<SafeAreaView style={{flex:1}}>
<Portal>
<Dialog visible={visible} onDismiss={hideDialog} style={{marginHorizontal:px2dp(50)}}>
<Dialog.ScrollArea >
<ScrollView contentContainerStyle={{paddingHorizontal: px2dp(50),height :px2dp(200)}}>
<List.Section>
{['清空'].map((item,index)=>{
return <List.Item
key={item}
title={item}
left={_ => <IconFont name={'clean'} size={px2dp(20)} style={{top:px2dp(5),marginRight:px2dp(20)}}/>}
onPress={cleanAllDevices}
/>
})}
</List.Section>
</ScrollView>
</Dialog.ScrollArea>
</Dialog>
</Portal>
<View style={styles.header}>
<Button
icon={()=><AntDesign
name={'search1'}
size={18}
color={"#fff"}
/>}
mode="contained"
onPress={startScan}
loading={isScanning}
style={{back以上是关于React Native BLE蓝牙通信 App开发的主要内容,如果未能解决你的问题,请参考以下文章