在suspendCancellableCoroutine中无法接收BroadcastReceiver消息求助
问题排查与解决方案
1. 补全函数参数,确保macAddress有效
你的obtainBluetoothDeviceBondState函数未接收macAddress参数,代码中直接引用的macAddress属于未定义状态(除非是类成员变量),这会导致即使收到广播,也会因地址不匹配无法触发后续逻辑。先修正函数定义:
@SuppressLint("MissingPermission") suspend fun Context.obtainBluetoothDeviceBondState(macAddress: String): Boolean { // ... 原有逻辑 }
2. 检查并申请必要权限
蓝牙绑定所需权限随Android版本不同有所区别:
- Android 11及以下:需声明
BLUETOOTH、BLUETOOTH_ADMIN权限 - Android 12+:需声明
BLUETOOTH_CONNECT、BLUETOOTH_ADMIN权限
在AndroidManifest.xml中添加权限声明,并在运行时申请危险权限:
<!-- Android 11及以下 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- Android 12+ --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
3. 修改广播注册的exported属性
BluetoothDevice.ACTION_BOND_STATE_CHANGED是系统进程发送的广播,使用ContextCompat.RECEIVER_NOT_EXPORTED会阻止外部进程(包括系统)向接收器发送消息,导致无法收到广播。需改为ContextCompat.RECEIVER_EXPORTED:
ContextCompat.registerReceiver( this, receiver, IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED), ContextCompat.RECEIVER_EXPORTED // 修改此处 )
4. 修正接收器注销逻辑
在onReceive和continuation.invokeOnCancellation中重复调用unregisterReceiver会引发异常,添加标志位避免重复注销:
var isReceiverRegistered = true val receiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (!isReceiverRegistered) return Log.e("Bluetooth", "onReceive") // ... 原有状态判断逻辑 isReceiverRegistered = false unregisterReceiver(this) } } continuation.invokeOnCancellation { if (isReceiverRegistered) { Log.e("Bluetooth", "unregisterReceiver") unregisterReceiver(receiver) isReceiverRegistered = false } }
5. 验证绑定请求发送成功
检查bluetoothManager.adapter.bondBluetoothDevice(macAddress)的返回值,如果为false,说明绑定请求发送失败,自然不会触发状态变化广播。此时需排查设备是否处于可连接状态、MAC地址是否正确。
内容的提问来源于stack exchange,提问作者Taku shousei
相关产品推荐
相关产品推荐

