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

相关推荐
货拉拉技术6 小时前
Hook植入日志协助定位问题方案
android
FlightYe7 小时前
Android投屏MirrorCast全链路
android
Ehtan_Zheng7 小时前
Kotlin const val vs val:字节码、性能与隐藏陷阱详解
android·kotlin
墨狂之逸才7 小时前
Android TV 垃圾应用清理指南
android
源来猿往7 小时前
记ffmpeg-8.1.1 之Android库编译(window)
android·ffmpeg
恋猫de小郭8 小时前
Android 17 正式版发布,全新 AI 和各种破坏性更新
android·前端·flutter
我命由我123458 小时前
Jetpack Room - Room 查询返回列表无需判空、LIKE 关键字
android·java·开发语言·java-ee·android jetpack·android-studio·android runtime
朝星8 小时前
Android开发[14]:网络优化之OkHttp
android·okhttp·kotlin
私人珍藏库8 小时前
[Android] FX Player-安卓全格式播放器-比MX播放器好用
android·学习·工具·软件·多功能
写点啥呢9 小时前
车机 Android 开机优化复盘:我怎么和 AI 一起把问题定位到 SystemUI
android·人工智能