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"
  }
}

相关推荐
2501_937860948 分钟前
MySQL表的操作:创建、查看、修改、删除完整实战
android·数据库·mysql
我就是妖怪9 小时前
KMP全栈开发:从Android到AI Agent的技术演进与实践
android·人工智能
心平气和量大福大11 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
阿pin12 小时前
Android随笔-Serializable与Parcelable
android·serializable·parcelable
天空之城--12 小时前
Android 事件分发机制深度解析——原理、源码与实战综合总结
android
阿pin13 小时前
Android随笔-AIDL
android·开发语言·aidl
2501_9160074714 小时前
Bundle ID 注册与管理 App ID 创建指南 命名规则 权限开关与删除注意事项
android·ios·小程序·https·uni-app·iphone·webview
雨白14 小时前
面向对象六大基本原则实战:从零重构支持引擎切换的网络框架
android·架构
张赐荣15 小时前
Android TalkBack 无障碍优化: 为控件自定义转子导航动作
android·microsoft
天空之城--17 小时前
Android Flutter行业动态与学习参考(2026年8月)
android·flutter