You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native Beacon检测问题:无法获取UUID等信息及替代库咨询

React Native 检测Beacon解决方案

一、修复react-native-ble-plx获取Beacon信息的问题

react-native-ble-plx是通用BLE库,Beacon(如iBeacon)的UUID、major、minor字段并不直接在device的serviceData或serviceUUIDs中,而是藏在广播数据的Manufacturer Data里。以下是修改后的可正常解析Beacon信息的代码:

import React, {useState, useEffect} from 'react';
import {View, Text, Button, FlatList} from 'react-native';
import { BleManager } from 'react-native-ble-plx';

const TAG = '[BeaconScanView]';
// iBeacon专属苹果厂商ID
const APPLE_MANUFACTURER_ID = 0x004C;

const BeaconScanView = () => {
  const [beacons, setBeacons] = useState([]);
  const [scanning, setScanning] = useState(false);

  const bleManager = new BleManager();

  useEffect(() => {
    return () => {
      bleManager.destroy();
    };
  }, []);

  // 解析iBeacon广播数据
  const parseIBeaconData = (manufacturerData) => {
    if (!manufacturerData) return null;
    const data = new Uint8Array(manufacturerData);
    
    // 验证是否为标准iBeacon格式
    if (data[0] !== APPLE_MANUFACTURER_ID & 0xff || data[1] !== (APPLE_MANUFACTURER_ID >> 8) & 0xff || data[2] !== 0x02 || data[3] !== 0x15) {
      return null;
    }

    // 提取UUID并格式化
    const uuid = Array.from(data.slice(4, 20))
      .map(byte => byte.toString(16).padStart(2, '0'))
      .join('')
      .replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5');
    
    // 提取major(大端序解析)
    const major = (data[20] << 8) | data[21];
    // 提取minor(大端序解析)
    const minor = (data[22] << 8) | data[23];
    // 提取校准信号强度
    const txPower = data[24];

    return { uuid, major, minor, txPower };
  };

  // 基于RSSI和TxPower计算更精准的距离
  const calculateDistance = (rssi, txPower) => {
    if (rssi === 0) return -1;
    const ratio = rssi * 1.0 / txPower;
    if (ratio < 1.0) {
      return Math.pow(ratio, 10);
    } else {
      return (0.89976) * Math.pow(ratio, 7.7095) + 0.111;
    }
  };

  const startScanning = async () => {
    if (scanning) return;

    setScanning(true);
    setBeacons([]);

    try {
      await bleManager.startDeviceScan(null, null, (error, device) => {
        if (error) {
          console.error('scan error:', error);
          return;
        }

        if (device) {
          const { name, id, rssi, manufacturerData } = device;
          const beaconData = parseIBeaconData(manufacturerData);
          
          if (beaconData) {
            const { uuid, major, minor, txPower } = beaconData;
            const beacon = {
              name,
              id,
              uuid,
              major,
              minor,
              rssi,
              txPower,
              distance: calculateDistance(rssi, txPower).toFixed(2)
            };

            setBeacons((prevBeacons) => {
              const existedIndex = prevBeacons.findIndex(b => b.id === beacon.id);
              if (existedIndex === -1) {
                return [...prevBeacons, beacon];
              }
              // 更新已有设备的实时数据
              const newBeacons = [...prevBeacons];
              newBeacons[existedIndex] = beacon;
              return newBeacons;
            });
          }
        }
      });

    } catch (error) {
      console.error('iBeacon error:', error);
    }
  };

  const stopScanning = () => {
    bleManager.stopDeviceScan();
    setScanning(false);
  };

  return (
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center', paddingTop: 20}}>
      <Button
        title={scanning ? '停止扫描' : '开始扫描'}
        onPress={scanning ? stopScanning : startScanning}
      />

      {beacons.length > 0 && (
        <FlatList
          style={{width: '100%', marginTop: 20}}
          data={beacons}
          keyExtractor={(item) => item.id}
          renderItem={({item}) => (
            <View style={{padding: 15, borderBottomWidth: 1, borderBottomColor: '#eee'}}>
              <Text>设备ID: {item.id}</Text>
              <Text>设备名称: {item.name || '未知'}</Text>
              <Text>UUID: {item.uuid}</Text>
              <Text>Major: {item.major}</Text>
              <Text>Minor: {item.minor}</Text>
              <Text>RSSI: {item.rssi}</Text>
              <Text>估算距离: {item.distance}m</Text>
            </View>
          )}
        />
      )}
    </View>
  );
};

export default BeaconScanView;

代码核心修改点:

  • 新增parseIBeaconData函数,专门解析iBeacon厂商广播数据,提取UUID、major、minor等核心标识
  • 替换距离计算逻辑,使用基于TxPower的专业算法,结果更精准
  • 增加设备数据更新逻辑,同一设备多次扫描时自动刷新距离等实时信息
  • 过滤非Beacon设备,只保留有效数据展示

二、替代库推荐

如果react-native-ble-plx不符合需求,以下几个专注Beacon或对Beacon支持更友好的库可以尝试:

  • react-native-beacons-manager:虽你认为它老旧,但它是专门针对Beacon的库,支持iBeacon和Eddystone,2024年仍有版本更新,可能是之前配置问题导致效果不佳,可重新排查权限和配置
  • react-native-ibeacon:轻量型iBeacon专属库,API设计更简洁,适配新版React Native
  • react-native-ble-manager:另一款通用BLE库,内置了Beacon数据解析工具,使用门槛更低

必做权限配置

  • iOS:在Info.plist中添加NSBluetoothAlwaysUsageDescription、NSBluetoothPeripheralUsageDescription权限声明;如需后台扫描,开启Background Modes中的Uses Bluetooth LE accessories
  • Android:在AndroidManifest.xml中添加BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限,部分系统版本需额外添加ACCESS_FINE_LOCATION权限;后台扫描需配置对应服务和权限

内容的提问来源于stack exchange,提问作者머랭쿠키

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:11:01