React Native 蓝牙开发实践:从权限配置到设备连接完整指南

React Native 蓝牙开发实践:从权限配置到设备连接完整指南

简介

本文基于 React Native 项目实践,介绍如何实现蓝牙低功耗(BLE)设备接入。重点讨论 Android 不同版本间的权限差异处理,以及蓝牙状态的实时监控等关键技术点。

在 React Native 项目中实现蓝牙低功耗(BLE)功能需要综合考虑多个方面:权限配置、设备扫描、连接管理、状态监控等。本文提供一套完整的开发方案,适用于大多数 BLE 设备接入场景。


架构设计

本文采用四层架构设计,实现代码结构的清晰分层和职责分离:

┌─────────────────────────────────────┐
│  第四层:应用层                      │
│  (业务代码使用 BluetoothManager)    │
└────────────────┬────────────────────┘
                 │
┌────────────────▼────────────────────┐
│  第三层:蓝牙管理器封装层            │
│  (BluetoothManager.ts)              │
└────────────────┬────────────────────┘
                 │
┌────────────────▼────────────────────┐
│  第二层:React Native 桥接层       │
│  (BlePro.ts)                       │
└────────────────┬────────────────────┘
                 │
┌────────────────▼────────────────────┐
│  第一层:Android 原生层              │
│  (BleProModule.kt)                  │
│         ↓                           │
│  BLE SDK / Android BLE API          │
└─────────────────────────────────────┘

架构层次说明

第一层:Android 原生层

  • 职责:直接调用 Android BLE API 或第三方 SDK,处理平台特有的权限检查和状态管理
  • 文件android/app/src/main/java/***/xxx/BleProModule.kt
  • 特点:处理 Android 平台底层操作,与硬件直接交互

第二层:React Native 桥接层

  • 职责:负责 JavaScript 与原生层之间的通信,处理事件转发和数据桥接
  • 文件src/native/BlePro.ts
  • 特点:提供类型安全的接口,处理跨平台通信

第三层:蓝牙管理器封装层

  • 职责:封装所有蓝牙操作,提供统一的 API 接口,管理状态和生命周期
  • 文件src/utils/bluetoothManager.ts
  • 特点:提供高级抽象,处理权限、状态管理、错误处理等

第四层:应用层

  • 职责:业务代码调用蓝牙管理器,实现业务逻辑
  • 特点:只需关注业务逻辑,无需关心底层实现细节

核心文件说明

层级 文件路径 说明
第一层 android/app/src/main/java/***/xxx/BleProModule.kt Android 原生模块,实现 BLE API 调用
第一层 android/app/src/main/AndroidManifest.xml Android 权限配置文件
第二层 src/native/BlePro.ts React Native 桥接层,处理原生模块通信
第三层 src/utils/bluetoothManager.ts 蓝牙管理器封装,统一管理蓝牙操作
第四层 业务代码文件 应用层业务逻辑实现

第一层:Android 原生层

Android 原生层负责直接调用 BLE API,处理平台特有的权限检查和状态管理。这是整个架构的基础层。

权限配置

权限配置是 BLE 开发的关键环节,Android 不同版本对蓝牙权限的要求存在显著差异,需要特别注意版本兼容性。

AndroidManifest.xml 配置

AndroidManifest.xml 中声明所需的蓝牙权限:

<!-- Android 12+ (API 31+) 新权限系统 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" 
                 android:usesPermissionFlags="neverForLocation"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>

<!-- Android 12 以下旧权限系统 -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

<!-- Android 10-11 需要位置权限(系统要求) -->
<uses-permission android:name="android.permission.A***ESS_FINE_LOCATION"/>

<!-- BLE 功能声明(建议设为 false,确保无蓝牙设备的兼容性) -->
<uses-feature android:name="android.hardware.bluetooth_le" 
              android:required="false"/>

关键要点:

  1. Android 12+ 引入新的权限系统,BLUETOOTH_SCANBLUETOOTH_CONNECT 必须同时声明,两者缺一不可
  2. Android 10-11 版本要求 A***ESS_FINE_LOCATION 权限,系统认为 BLE 扫描可能用于位置定位
  3. neverForLocation 标志用于声明该权限不用于定位目的,避免 Google Play 审核时被拒绝

原生模块实现

原生模块(BleProModule.kt)负责直接调用 BLE API,处理平台特有的逻辑。

模块注册

MainApplication.kt 中注册原生模块:

class MainApplication : Application(), ReactApplication {
  override val reactNativeHost: ReactNativeHost =
      object : DefaultReactNativeHost(this) {
        override fun getPackages(): List<ReactPackage> =
            PackageList(this).packages.apply {
              add(BleProPackage()) // 注册蓝牙模块
            }
      }
}

核心方法实现

原生模块提供以下核心方法:

  • initialize() - 初始化 BLE 服务,检查蓝牙状态
  • scan() - 开始扫描设备
  • stopScan() - 停止扫描
  • connect(deviceId) - 连接设备
  • disconnect() - 断开连接
  • checkBluetoothEnabled() - 检查蓝牙是否开启
  • checkBluetoothSupported() - 检查蓝牙是否支持

事件发送

原生层通过 React Native 事件系统向 JavaScript 层发送事件:

  • ble.serviceReady - 服务就绪事件
  • ble.deviceFound - 设备发现事件
  • ble.connectState - 连接状态事件
  • ble.error - 错误事件

运行时权限处理

除了在 AndroidManifest.xml 中声明权限外,还需要在代码中处理运行时权限请求。不同 Android 版本的权限处理机制存在差异,需要分别处理。

权限检查实现

根据 Android 版本动态检查对应权限:

const checkBluetoothPermissions = async (): Promise<boolean> => {
  if (Platform.OS !== 'android') return true;
  
  const sdk = Number(Platform.Version);
  if (sdk >= 31) {
    // Android 12+ 需要两个新权限
    const hasScan = await PermissionsAndroid.check(
      PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN
    );
    const hasConnect = await PermissionsAndroid.check(
      PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT
    );
    return hasScan && hasConnect;
  } else {
    // Android 10-11 需要位置权限(没办法,Google 的要求)
    const hasLocation = await PermissionsAndroid.check(
      PermissionsAndroid.PERMISSIONS.A***ESS_FINE_LOCATION
    );
    return hasLocation;
  }
};

请求权限

如果权限未授予,需要主动请求:

const requestBluetoothPermissions = async (): Promise<boolean> => {
  if (Platform.OS !== 'android') return true;
  
  try {
    const sdk = Number(Platform.Version);
    if (sdk >= 31) {
      // Android 12+ 需要同时请求两个权限
      const res = await PermissionsAndroid.requestMultiple([
        PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
        PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
      ]);
      return (
        res[PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN] === 'granted' &&
        res[PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT] === 'granted'
      );
    } else {
      // Android 10-11 只请求位置权限
      const fine = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.A***ESS_FINE_LOCATION
      );
      return fine === 'granted';
    }
  } catch (error) {
    console.log('请求权限失败:', error);
    return false;
  }
};

实现建议:

  • 采用按需请求策略,在用户实际使用蓝牙功能时再请求权限,而非应用启动时,以提升用户体验
  • 当用户拒绝权限时,应提供清晰的提示信息,引导用户前往系统设置手动开启权限

第二层:React Native 桥接层

桥接层负责 JavaScript 与原生层之间的通信,提供类型安全的接口,处理事件转发和数据桥接。

桥接层实现

桥接层文件 src/native/BlePro.ts 的主要职责:

模块导入

import {
  NativeModules,
  NativeEventEmitter,
  type NativeModule,
  EmitterSubscription,
} from 'react-native';

const { BleProModule } = NativeModules;

核心 API 封装

桥接层封装原生模块的方法:

export const BlePro = {
  // 基础操作
  initialize: () => BleProModule?.initialize(),
  scan: () => BleProModule?.scan(),
  stopScan: () => BleProModule?.stopScan(),
  connect: (deviceId: string) => BleProModule?.connect(deviceId),
  disconnect: () => BleProModule?.disconnect(),
  
  // 状态检查
  checkBluetoothEnabled: () => BleProModule?.checkBluetoothEnabled(),
  checkBluetoothSupported: () => BleProModule?.checkBluetoothSupported(),
  
  // 事件监听器
  addServiceReadyListener: (cb: (ready: boolean) => void) => ...,
  addDeviceFoundListener: (cb: (d: BleDevice) => void) => ...,
  addConnectStateListener: (cb: (s: { model: number; state: number }) => void) => ...,
  addErrorListener: (cb: (error: ErrorInfo) => void) => ...,
};

事件系统

桥接层通过 NativeEventEmitter 处理原生层事件:

  • 将原生事件转换为 JavaScript 事件
  • 提供类型安全的事件监听接口
  • 处理事件订阅和取消订阅

第三层:蓝牙管理器封装层

蓝牙管理器封装层提供高级抽象,统一管理所有蓝牙操作,处理权限、状态管理、错误处理等复杂逻辑。

BluetoothManager 设计

BluetoothManager 类是蓝牙功能的核心封装,提供统一的 API 接口。

类结构设计

export class BluetoothManager {
  private state: BluetoothState;
  private callbacks: BluetoothCallbacks;
  private subscriptions: any[];
  private scanTimer: number | null;
  
  constructor(callbacks: BluetoothCallbacks);
  async initialize(): Promise<void>;
  async scan(): Promise<void>;
  async stopScan(): Promise<void>;
  async connect(device: BleDevice): Promise<void>;
  async disconnect(): Promise<void>;
  getState(): BluetoothState;
  destroy(): void;
}

回调接口定义

export interface BluetoothCallbacks {
  onStateChange?: (state: BluetoothState) => void;
  onDeviceFound?: (device: BleDevice) => void;
  onDeviceConnected?: (model: number) => void;
  onDeviceDisconnected?: () => void;
  onError?: (error: string) => void;
  on***patibilityError?: (error: ErrorInfo) => void;
  onNavigateToSettings?: () => void;
}

核心功能实现

1. 初始化

初始化蓝牙服务,检查权限和蓝牙状态:

try {
  // initialize() 会自动检查蓝牙状态和权限
  await bluetoothManager.initialize();
  console.log('蓝牙服务初始化成功');
} catch (error) {
  if (error.message === 'BLUETOOTH_DISABLED') {
    // 蓝牙未开启,提示用户
    Alert.alert('蓝牙未开启', '请先开启设备蓝牙功能');
  } else {
    console.error('初始化失败:', error);
  }
}

初始化流程包括:

  1. 断开现有连接(如果有)
  2. 调用桥接层的 BlePro.initialize()
  3. 检查错误类型,处理蓝牙未开启等特殊情况
  4. 注册事件监听器

2. 蓝牙状态检查

提供蓝牙状态检查方法:

// 检查蓝牙是否开启
async checkBluetoothEnabled(): Promise<boolean> {
  return await BlePro.checkBluetoothEnabled();
}

// 检查蓝牙是否支持
async checkBluetoothSupported(): Promise<boolean> {
  return await BlePro.checkBluetoothSupported();
}

3. 设备扫描

扫描功能实现:

async scan(): Promise<void> {
  // 1. 检查是否已在扫描中
  if (this.state.scanning) return;
  
  // 2. 请求权限
  const ok = await this.requestBlePermissions();
  if (!ok) return;
  
  // 3. 更新状态
  this.updateState({ scanning: true, devices: [], error: null });
  
  // 4. 调用桥接层方法
  await BlePro.scan();
  
  // 5. 设置超时自动停止
  this.scanTimer = setTimeout(() => {
    this.stopScan();
  }, 15000);
}

扫描流程:

  1. 检查扫描状态,避免重复扫描
  2. 请求 BLE 权限
  3. 更新状态为扫描中
  4. 调用桥接层的 BlePro.scan() 方法
  5. 设置 15 秒超时自动停止
  6. 通过 onDeviceFound 回调接收设备
4. 设备连接

连接功能实现:

async connect(device: BleDevice): Promise<void> {
  // 1. 设置设备接口
  await BlePro.setInterfaces(device.model);
  
  // 2. 停止扫描
  await this.stopScan();
  
  // 3. 执行连接
  const deviceId = device.address || device.name;
  await BlePro.connect(deviceId);
  
  // 4. 更新连接状态
  this.updateState({ connectedModel: device.model });
}

连接流程:

  1. 设置设备接口类型
  2. 停止当前扫描
  3. 调用桥接层的 BlePro.connect() 方法
  4. 使用设备 MAC 地址或名称连接
  5. 通过 ble.connectState 事件接收连接结果(state = 3 表示成功)

5. 状态管理

BluetoothManager 维护内部状态,并通过回调通知应用层:

export interface BluetoothState {
  ready: boolean;           // 服务是否就绪
  devices: BleDevice[];     // 已发现的设备列表
  scanning: boolean;        // 是否正在扫描
  connectedModel: number | null;  // 已连接的设备型号
  error: string | null;     // 错误信息
}

6. 生命周期管理

提供销毁方法,清理资源:

destroy(): void {
  // 移除所有事件监听器
  this.subscriptions.forEach(sub => sub.remove());
  
  // 清除扫描定时器
  if (this.scanTimer) {
    clearTimeout(this.scanTimer);
  }
}

第四层:应用层

应用层是业务代码使用蓝牙功能的地方,只需调用 BluetoothManager 提供的 API 接口即可。


错误处理

BLE 开发过程中可能遇到多种错误情况。本节整理了常见错误类型及对应的解决方案。

错误代码定义

项目定义了以下错误代码:

// 在 BleProModule.kt 中定义
const ERROR_INIT_FAILED = "INIT_FAILED"
const ERROR_SCAN_FAILED = "SCAN_FAILED"
const ERROR_CONNECT_FAILED = "CONNECT_FAILED"
const ERROR_DISCONNECT_FAILED = "DISCONNECT_FAILED"
const ERROR_SET_INTERFACE_FAILED = "SET_INTERFACE_FAILED"
const ERROR_DEVICE_NOT_SUPPORTED = "DEVICE_NOT_SUPPORTED"
const ERROR_PERMISSION_DENIED = "PERMISSION_DENIED"
const ERROR_BLUETOOTH_DISABLED = "BLUETOOTH_DISABLED"

错误监听

const bluetoothManager = new BluetoothManager({
  onError: (error) => {
    // 通用错误
    console.error('蓝牙错误:', error);
  },
  on***patibilityError: (error) => {
    // 兼容性错误处理(提供用户友好的错误提示)
    // error: {
    //   errorCode: string,
    //   errorMessage: string,
    //   details?: string
    // }
  
    switch (error.errorCode) {
      case 'BLUETOOTH_DISABLED':
        // 蓝牙未开启
        Alert.alert('蓝牙未开启', '请先开启设备蓝牙功能');
        break;
      case 'PERMISSION_DENIED':
        // 权限被拒绝
        Alert.alert('权限不足', '需要蓝牙权限以扫描与连接设备', [
          { text: '取消', style: 'cancel' },
          { 
            text: '去设置', 
            onPress: () => Linking.openSettings() 
          },
        ]);
        break;
      case 'DEVICE_NOT_SUPPORTED':
        // 设备不支持
        Alert.alert('设备不支持', error.errorMessage);
        break;
      // ... 其他错误
    }
  },
});

原生层错误处理

原生层会通过 ble.error 事件发送错误:

private fun sendErrorEvent(
  errorCode: String, 
  errorMessage: String, 
  details: String? = null
) {
  val map = Arguments.createMap()
  map.putString("errorCode", errorCode)
  map.putString("errorMessage", errorMessage)
  if (details != null) {
    map.putString("details", details)
  }
  map.putLong("timestamp", System.currentTimeMillis())
  sendEvent("ble.error", map)
}

最佳实践

基于实际项目经验,总结以下最佳实践,有助于提升开发效率和代码质量:

1. 生命周期管理

useEffect(() => {
  // 创建蓝牙管理器
  const manager = new BluetoothManager({ /* callbacks */ });
  
  // 初始化
  manager.initialize().then(() => {
    manager.scan();
  });
  
  // 清理
  return () => {
    manager.disconnect();
    manager.destroy(); // 移除所有监听器
  };
}, []);

2. 状态管理

使用 useRef 存储蓝牙状态,避免不必要的重新渲染:

const bluetoothStateRef = useRef<BluetoothState>({
  ready: false,
  devices: [],
  scanning: false,
  connectedModel: null,
  error: null,
});

// 在回调中更新 ref
onStateChange: (state) => {
  bluetoothStateRef.current = { ...bluetoothStateRef.current, ...state };
}

3. 自动重连

设备断开后自动尝试重连:

onDeviceDisconnected: () => {
  // 停止当前活动
  stopMeasurement();
  
  // 延迟后重新扫描
  setTimeout(async () => {
    try {
      await bluetoothManager.scan();
    } catch (error) {
      console.error('重连失败:', error);
    }
  }, 1000);
}

4. 蓝牙状态监控

定期检查蓝牙状态,处理用户手动关闭蓝牙的情况:

useEffect(() => {
  const interval = setInterval(async () => {
    const isEnabled = await bluetoothManager.checkBluetoothEnabled();
    if (!isEnabled && bluetoothStateRef.current.ready) {
      // 蓝牙被关闭,停止所有活动
      await bluetoothManager.stopScan();
      bluetoothStateRef.current.ready = false;
    }
  }, 1000);
  
  return () => clearInterval(interval);
}, []);

5. 权限请求时机

在真正需要蓝牙功能时再请求权限,避免应用启动时弹窗:

// 扫描前请求权限
async scan() {
  const ok = await this.requestBlePermissions();
  if (!ok) {
    // 权限被拒绝时,提供相应提示信息
    return;
  }
  // 继续扫描...
}

6. 错误恢复

对于可恢复的错误,自动重试:

let retryCount = 0;
const MAX_RETRIES = 3;

const initializeWithRetry = async () => {
  try {
    await bluetoothManager.initialize();
    retryCount = 0; // 成功后重置
  } catch (error) {
    if (retryCount < MAX_RETRIES) {
      retryCount++;
      setTimeout(initializeWithRetry, 1000 * retryCount); // 指数退避
    } else {
      // 达到最大重试次数,显示错误
      Alert.alert('初始化失败', '请检查蓝牙设置');
    }
  }
};

基础使用

1. 创建蓝牙管理器

import { BluetoothManager } from '../utils/bluetoothManager';

const bluetoothManager = new BluetoothManager({
  onStateChange: (state) => {
    // 蓝牙状态更新
    console.log('蓝牙状态:', state);
  },
  onDeviceFound: (device) => {
    // 发现新设备
    console.log('发现设备:', device);
  },
  onDeviceConnected: (model) => {
    // 设备连接成功
    console.log('设备连接成功:', model);
  },
  onDeviceDisconnected: () => {
    // 设备断开
    console.log('设备断开连接');
  },
  onError: (error) => {
    // 错误处理
    console.error('蓝牙错误:', error);
  },
});

2. 初始化和扫描

// 初始化蓝牙服务
await bluetoothManager.initialize();

// 开始扫描设备
await bluetoothManager.scan();

3. 连接设备

const device = bluetoothManager.getState().devices[0];
await bluetoothManager.connect(device);

4. 监听蓝牙状态变化

useEffect(() => {
  const checkBluetoothState = async () => {
    const isEnabled = await bluetoothManager.checkBluetoothEnabled();
    if (!isEnabled) {
      // 蓝牙被关闭,停止扫描
      await bluetoothManager.stopScan();
    }
  };
  
  const interval = setInterval(checkBluetoothState, 1000);
  return () => clearInterval(interval);
}, []);

完整示例

import React, { useEffect, useRef, useState } from 'react';
import { BluetoothManager } from '../utils/bluetoothManager';
import { BleDevice } from '../native/BlePro';
import { Alert, Platform } from 'react-native';

const BluetoothExample: React.FC = () => {
  const [devices, setDevices] = useState<BleDevice[]>([]);
  const [connectedModel, setConnectedModel] = useState<number | null>(null);
  const [scanning, setScanning] = useState(false);
  
  const bluetoothManagerRef = useRef<BluetoothManager | null>(null);

  useEffect(() => {
    // 创建蓝牙管理器
    bluetoothManagerRef.current = new BluetoothManager({
      onStateChange: (state) => {
        setDevices(state.devices);
        setConnectedModel(state.connectedModel);
        setScanning(state.scanning);
      },
      onDeviceFound: (device) => {
        console.log('发现设备:', device);
      },
      onDeviceConnected: (model) => {
        console.log('设备连接成功:', model);
      },
      onDeviceDisconnected: () => {
        console.log('设备断开');
      },
      onError: (error) => {
        Alert.alert('蓝牙错误', error);
      },
      on***patibilityError: (error) => {
        if (error.errorCode === 'BLUETOOTH_DISABLED') {
          Alert.alert('蓝牙未开启', '请先开启蓝牙');
        }
      },
    });

    // 初始化并开始扫描
    const initBluetooth = async () => {
      try {
        await bluetoothManagerRef.current?.initialize();
        await bluetoothManagerRef.current?.scan();
      } catch (error) {
        console.error('初始化失败:', error);
      }
    };

    initBluetooth();

    // 清理
    return () => {
      bluetoothManagerRef.current?.disconnect();
      bluetoothManagerRef.current?.destroy();
    };
  }, []);

  // 连接设备
  const handleConnect = async (device: BleDevice) => {
    try {
      await bluetoothManagerRef.current?.connect(device);
    } catch (error) {
      Alert.alert('连接失败', String(error));
    }
  };

  // 断开连接
  const handleDisconnect = async () => {
    try {
      await bluetoothManagerRef.current?.disconnect();
    } catch (error) {
      console.error('断开失败:', error);
    }
  };

  return (
    <View>
      <Text>扫描中: {scanning ? '是' : '否'}</Text>
      <Text>已连接: {connectedModel || '无'}</Text>
      <Text>设备数量: {devices.length}</Text>
    
      {devices.map((device, index) => (
        <TouchableOpacity
          key={index}
          onPress={() => handleConnect(device)}
        >
          <Text>{device.name} ({device.model})</Text>
        </TouchableOpacity>
      ))}
    
      {connectedModel && (
        <Button title="断开连接" onPress={handleDisconnect} />
      )}
    </View>
  );
};

权限检查示例

import { PermissionsAndroid, Platform } from 'react-native';

const checkBluetoothPermissions = async (): Promise<boolean> => {
  if (Platform.OS !== 'android') return true;

  try {
    const sdk = Number(Platform.Version);
    if (sdk >= 31) {
      // Android 12+
      const hasScan = await PermissionsAndroid.check(
        PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN
      );
      const hasConnect = await PermissionsAndroid.check(
        PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT
      );
      return hasScan && hasConnect;
    } else {
      // Android 10-11
      const hasLocation = await PermissionsAndroid.check(
        PermissionsAndroid.PERMISSIONS.A***ESS_FINE_LOCATION
      );
      return hasLocation;
    }
  } catch (error) {
    console.error('检查权限失败:', error);
    return false;
  }
};

总结

本文介绍了一套完整的 React Native BLE 开发方案,采用三层架构设计,通过 BluetoothManager 统一管理蓝牙操作,开发者可专注于业务逻辑实现,底层权限管理、状态监控、设备扫描和连接等细节已封装处理。

核心要点

  1. 权限管理 - Android 不同版本的权限机制差异显著,需特别关注版本兼容性
  2. 状态监控 - 实时监听蓝牙状态变化,处理用户手动关闭蓝牙等场景
  3. 错误处理 - 建立完善的错误处理机制,为用户提供友好的错误提示
  4. 自动重连 - 实现设备断开后的自动重连机制,提升用户体验
  5. 资源管理 - 组件卸载时及时清理蓝牙资源,防止内存泄漏

常见问题

  1. Android 12+ 权限配置 - 仅声明 BLUETOOTH_SCAN 会导致连接功能不可用,必须同时声明 BLUETOOTH_CONNECT
  2. 状态监听缺失 - 未实现蓝牙状态监听可能导致应用无法响应蓝牙关闭事件,停留在扫描状态
  3. 权限请求时机 - 在应用启动时请求权限影响用户体验,建议采用按需请求策略

建议

  • 优先完成权限配置,这是最容易出现问题的环节
  • 实现完整的蓝牙状态监控,确保应用能正确响应状态变化
  • 建立全面的错误处理机制,覆盖各种异常情况
  • 在不同 Android 版本设备上充分测试,特别是 Android 12 前后的版本差异

通过遵循本文介绍的方案和最佳实践,可以有效解决 React Native BLE 开发中的常见问题,提升应用的稳定性和用户体验。

转载请说明出处内容投诉
CSS教程网 » React Native 蓝牙开发实践:从权限配置到设备连接完整指南

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买