android 蓝牙连接-兼容旧版本

react-native-ble-manager 扫描结果突然变成 空数组 ,通常不是代码逻辑问题,而是 权限 / 系统策略 / BLE 设备广播变化。你这段代码本身逻辑是没问题的。常见原因主要有下面几类(按概率排序):


1️⃣ Android 12+ 蓝牙权限变化(最常见)

如果你的 targetSdkVersion ≥ 31 (Android 12) ,必须增加新的蓝牙权限,否则 scan 会成功执行但返回空设备

AndroidManifest.xml 必须增加

复制代码
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

兼容旧版本:

复制代码
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

同时需要运行时权限

React Native 代码:

复制代码
import {PermissionsAndroid} from 'react-native';

async function requestPermissions() {
  await PermissionsAndroid.requestMultiple([
    PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
    PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
    PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
  ]);
}

启动 BLE 前调用:

复制代码
await requestPermissions();

否则:

复制代码
getDiscoveredPeripherals() = []

2️⃣ 没有监听

BleManagerDiscoverPeripheral

事件

BleManager.getDiscoveredPeripherals() 依赖 扫描事件缓存

新版 Android 有时不会自动缓存。

建议监听事件:

复制代码
import {NativeEventEmitter, NativeModules} from 'react-native';

const bleManagerEmitter = new NativeEventEmitter(NativeModules.BleManager);

bleManagerEmitter.addListener(
  'BleManagerDiscoverPeripheral',
  (peripheral) => {
    console.log('discover', peripheral);
  }
);

如果这里 没有任何输出

说明 scan 根本没有发现设备


3️⃣ 打印机不再广播 name

很多 BLE 打印机升级固件后:

复制代码
peripheral.name = null

设备名称在:

复制代码
peripheral.advertising.localName

所以建议改为:

复制代码
const printer = peripherals.find(
  p =>
    p.name === printerName ||
    p.advertising?.localName === printerName
);

4️⃣ scan 参数问题

你现在:

复制代码
BleManager.scan([], 5, true);

第三个参数 true 是 allowDuplicates

建议改成:

复制代码
BleManager.scan([], 5, false);

有些 Android 会过滤。


5️⃣ Android 没打开定位

Android BLE 扫描必须开启:

复制代码
Location Service

否则:

复制代码
scan = []

6️⃣ iOS 17 / Android 13 扫描策略改变

如果是新系统:

扫描必须:

复制代码
BleManager.start({showAlert: false})

在扫描前调用:

复制代码
await BleManager.start({showAlert: false});

7️⃣ 你的 timeout 可能太短

你扫描:

复制代码
scan 5 秒
timeout 6 秒

建议:

复制代码
scan 8 秒
timeout 9 秒

推荐改进代码

复制代码
_scan(printerName) {
  return new Promise(async (resolve, reject) => {
    try {

      await BleManager.start({showAlert:false})

      console.log('===========> scanAndConnect');

      await BleManager.scan([], 8, false);

      setTimeout(async () => {
        try {

          const peripherals = await BleManager.getDiscoveredPeripherals();

          console.log('peripherals', peripherals);

          const printer = peripherals.find(p =>
            p.name === printerName ||
            p.advertising?.localName === printerName
          );

          resolve(printer);

        } catch (e) {
          console.log('_scan get device failed', e);
          reject(e);
        }

      }, 9000);

    } catch (e) {
      console.log('_scan failed', e);
      reject(e);
    }
  });
}

8️⃣ 最关键的排查方法(强烈推荐)

先打印:

复制代码
console.log(JSON.stringify(peripherals,null,2))

看真实返回结构。

很多时候你会看到:

复制代码
{
  "name": null,
  "advertising": {
    "localName": "Printer_123"
  }
}

相关推荐
鹏多多.2 小时前
Flutter使用screenshot进行截屏和截长图以及分享保存的全流程指南
android·前端·flutter·ios·前端框架
Flywith244 小时前
【每日一技】Warp Workflow 使用示例
android·前端
冬奇Lab5 小时前
JobScheduler与WorkManager:任务调度机制
android·源码阅读
summerkissyou19876 小时前
Android-view-绘制流程及自定义例子
android·app
常利兵7 小时前
Android “解锁”屏幕方向:APP适配新征程
android·gitee
红藕香残玉簟秋9 小时前
【安卓学习】配置开发环境
android·学习
用户69371750013849 小时前
Android R8 深度解析:为什么 Google 用R8取代 ProGuard?
android·android studio·android jetpack
seabirdssss9 小时前
联想拯救者Y7000P上使用ADB无法监听到通过USB连接的安卓设备
android·adb