ReactNative ble 管理器未从 IOS 上的外围设备读取数据

问题描述

我正在为 IOS 和 Android 平台构建一个 ReactNative 应用程序。我的应用程序需要通过 BLE 通信从另一台设备读取数据。我正在使用这个包来实现 BLE 通信,https://github.com/innoveit/react-native-ble-manager。我在 IOS 上接收特征数据时遇到问题,即使它在 Android 平台上按预期工作。

我在 info.plist 文件添加了以下内容

Privacy - Bluetooth Always Usage Description: App needs to use Bluetooth to receive data from WaterRower machine

我有一个组件可以扫描并列出 BLE 设备,如下所示。它被称为,BleDeviceList.js

import React,{
  useState,useEffect,} from 'react';
import {
  SafeAreaView,StyleSheet,ScrollView,View,Text,StatusBar,NativeModules,NativeEventEmitter,Button,Platform,PermissionsAndroid,FlatList,TouchableHighlight,} from 'react-native';

import {
  Colors,} from 'react-native/Libraries/NewAppScreen';

import BleManager from 'react-native-ble-manager';
const BleManagerModule = NativeModules.BleManager;
const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);

const BleDeviceList = (props) => {
  const [isScanning,setIsScanning] = useState(false);
  const peripherals = new Map();
  const [list,setList] = useState([]);
  const [ connectedDevices,setConnectedDevices ] = useState([ ]);
  const [ permissionsAllowed,setPermissionsAllowed ] = useState(false)


  const startScan = () => {
    if (!isScanning) {
      BleManager.scan([],3,true).then((results) => {
        console.log('Scanning...');
        setIsScanning(true);
      }).catch(err => {
        console.error(err);
      });
    }
  }

  const handleStopScan = () => {
    console.log('Scan is stopped');
    setIsScanning(false);
  }

  const handledisconnectedPeripheral = (data) => {
    let peripheral = peripherals.get(data.peripheral);
    if (peripheral) {
      peripheral.connected = false;
      peripherals.set(peripheral.id,peripheral);
      setList(Array.from(peripherals.values()));
    }
    console.log('disconnected from ' + data.peripheral);
  }

  const handleUpdateValueForCharacteristic = (data) => {
    console.log('Received data from ' + data.peripheral + ' characteristic ' + data.characteristic,data.value);
  }

  const retrieveConnected = () => {
    BleManager.getConnectedperipherals([]).then((results) => {
      if (results.length == 0) {
        console.log('No connected peripherals')
      }
      console.log(results);
      for (var i = 0; i < results.length; i++) {
        var peripheral = results[i];
        peripheral.connected = true;
        peripherals.set(peripheral.id,peripheral);
        setList(Array.from(peripherals.values()));
      }
    });
  }

  const handlediscoverPeripheral = (peripheral) => {
    console.log('Got ble peripheral',peripheral);
    if (!peripheral.name) {
      peripheral.name = 'NO NAME';
    }
    peripherals.set(peripheral.id,peripheral);
    setList(Array.from(peripherals.values()));
  }

  const isConnected = (peripheral) => {
    return connectedDevices.filter(cd => cd.id == peripheral.id).length > 0;
  }

  const toggleConnectPeripheral = (peripheral) => {
    if (peripheral){
      if (isConnected(peripheral)){
        BleManager.disconnect(peripheral.id);
        setConnectedDevices(connectedDevices.filter(cd => cd.id != peripheral.id))
      }else{
        BleManager.connect(peripheral.id).then(() => {
          let tempConnnectedDevices = [ ...connectedDevices ]
          tempConnnectedDevices.push(peripheral);
          setConnectedDevices(tempConnnectedDevices);
          props.navigation.push('BleRowingSession',{ peripheral: peripheral });

          let p = peripherals.get(peripheral.id);
          if (p) {
            p.connected = true;
            peripherals.set(peripheral.id,p);
            setList(Array.from(peripherals.values()));

            props.navigation.push('BleDeviceServiceList',{ peripheral: peripheral });
          }
          console.log('Connected to ' + peripheral.id);
        }).catch((error) => {
          console.log('Connection error',error);
        });
      }
    }

  }

  useEffect(() => {
    BleManager.start({showAlert: false});

    bleManagerEmitter.addListener('BleManagerdiscoverPeripheral',handlediscoverPeripheral);
    bleManagerEmitter.addListener('BleManagerStopScan',handleStopScan );
    bleManagerEmitter.addListener('BleManagerdisconnectPeripheral',handledisconnectedPeripheral );
    bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic',handleUpdateValueForCharacteristic );

    if (Platform.OS === 'android' && Platform.Version >= 23) {
      PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION).then((result) => {
          if (result) {
            console.log("Permission is OK");
            setPermissionsAllowed(true);
          } else {
            PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION).then((result) => {
              if (result) {
                console.log("User accept");
                setPermissionsAllowed(true);
              } else {
                console.log("User refuse");
                setPermissionsAllowed(false);
              }
            });
          }
      });
    } else {
      setPermissionsAllowed(true)
    }

    return (() => {
      console.log('unmount');
      bleManagerEmitter.removeListener('BleManagerdiscoverPeripheral',handlediscoverPeripheral);
      bleManagerEmitter.removeListener('BleManagerStopScan',handleStopScan );
      bleManagerEmitter.removeListener('BleManagerdisconnectPeripheral',handledisconnectedPeripheral );
      bleManagerEmitter.removeListener('BleManagerDidUpdateValueForCharacteristic',handleUpdateValueForCharacteristic );
    })
  },[]);

  const renderConnectButton = (item) => {
    if (isConnected(item)) {
      return null
    }

    return (
      <Button
      title="Connect"
      onPress={() => {
          toggleConnectPeripheral(item)
      }}
      />
    )
  }

  const renderdisconnectButton = (item) => {
    if (! isConnected(item)) {
      return null
    }

    return (
      <Button
      title="disconnect"
      onPress={() => {
        toggleConnectPeripheral(item)
      }}
      />
    )
  }

  const renderItem = (item) => {
    const color = item.connected ? 'green' : '#fff';
    return (
      <TouchableHighlight>
        <View style={[styles.row,{backgroundColor: color}]}>
          <Text style={{fontSize: 12,textAlign: 'center',color: '#333333',padding: 10}}>{item.name}</Text>
          <Text style={{fontSize: 10,padding: 2}}>RSSI: {item.RSSi}</Text>
          <Text style={{fontSize: 8,padding: 2,paddingBottom: 20}}>{item.id}</Text>
          {renderConnectButton(item)}
          {renderdisconnectButton(item)}
        </View>
      </TouchableHighlight>
    );
  }

  const renderContent = () => {
    if (! permissionsAllowed) {
      return <Text>Bluetooth and locations permissions are required.</Text>
    }

    return (
        <>
          <StatusBar barStyle="dark-content" />
          <SafeAreaView>
            <ScrollView
                contentInsetAdjustmentBehavior="automatic"
                style={styles.scrollView}>
              {global.HermesInternal == null ? null : (
                  <View style={styles.engine}>
                    <Text style={styles.footer}>Engine: Hermes</Text>
                  </View>
              )}
              <View style={styles.body}>

                <View style={{margin: 10}}>
                  <Button
                      title={'Scan Bluetooth (' + (isScanning ? 'on' : 'off') + ')'}
                      onPress={() => startScan() }
                  />
                </View>

                <View style={{margin: 10}}>
                  <Button title="Retrieve connected peripherals" onPress={() => retrieveConnected() } />
                </View>

                {(list.length == 0) &&
                <View style={{flex:1,margin: 20}}>
                  <Text style={{textAlign: 'center'}}>No peripherals</Text>
                </View>
                }

              </View>
            </ScrollView>
            <FlatList
                data={list}
                renderItem={({ item }) => renderItem(item) }
                keyExtractor={item => item.id}
            />
          </SafeAreaView>
        </>
    )
  }

  return (
    renderContent()
  );
};

const styles = StyleSheet.create({
  scrollView: {
    backgroundColor: Colors.lighter,},engine: {
    position: 'absolute',right: 0,body: {
    backgroundColor: Colors.white,sectionContainer: {
    marginTop: 32,paddingHorizontal: 24,sectionTitle: {
    fontSize: 24,fontWeight: '600',color: Colors.black,sectionDescription: {
    marginTop: 8,fontSize: 18,fontWeight: '400',color: Colors.dark,highlight: {
    fontWeight: '700',footer: {
    color: Colors.dark,fontSize: 12,padding: 4,paddingRight: 12,textAlign: 'right',});

export default BleDeviceList;

正如您在代码中看到的,当点击 Connect 按钮时,它会将用户重定向到另一个组件,该组件从另一个设备读取数据。下面是从另一个设备读取数据的 BleRowingSession.js。

import React,{ useEffect,useState } from 'react';
import { Text,ScrollView } from 'react-native';
import BleManager from 'react-native-ble-manager';
const BleManagerModule = NativeModules.BleManager;
const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);

const serviceId = "00001826-0000-1000-8000-00805F9B34FB";
const characteristicId = "00002AD1-0000-1000-8000-00805F9B34FB";

let readDataCache = "";

const BleRowingSession = (props) => {
  let peripheral = props.route.params.peripheral;
  const [ readData,setReadData ] = useState("");

  const setUpBleNotification = () => {
    BleManager.retrieveServices(peripheral.id).then((peripheralData) => {
              console.log('Retrieved peripheral services',peripheralData);

              setTimeout(() => {
                BleManager.startNotification(peripheral.id,serviceId,characteristicId).then(() => {
                  console.log('Started notification on ' + peripheral.id);
                  bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic',(data) => {
                    readDataCache = readDataCache + "\n" + data.value.toString()
                    setReadData(readDataCache);
                  });
                  setTimeout(() => {

                  },500);
                }).catch((error) => {
                  console.log('Notification error',error);
                });
              },500)
            });
  }

  useEffect(() => {
    setUpBleNotification()
  },[ ])

  return (
    <View style={styles.container}>
      <ScrollView>
        <Text>Ble Rowing Session</Text>
        <Text>{readData}</Text>
      </ScrollView>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,justifyContent: "center",alignItems: "center"
  }
})

export default BleRowingSession;

目前,服务 ID 和特征 ID 是硬编码的。当然,我必须在显示 BLE 设备列表的第一页上选择正确的设备。

当我运行代码时,它在 Android 设备上按预期工作,它正在接收特征值。当我在实际的 IOS 设备上运行代码时,它没有接收任何数据。但它可以扫描设备并连接到它们。我的代码有什么问题,我该如何解决

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...