Android BLE应用如何检测外设连接尝试及获取连接失败原因?
问题根因
Android 原生 BluetoothGattServerCallback 的 onConnectionStateChange 回调不会触发 STATE_CONNECTING 状态,该状态仅用于 GATT 客户端(即 Android 主动作为发起方连接外设的场景),服务端场景下系统默认不会上报正在连接的中间状态,所以你的对应分支永远无法触发。
解决方案
1. 监听广播获取连接请求事件
你可以通过动态注册广播接收器,监听蓝牙ACL连接相关的系统广播,即可在底层收到设备连接请求时第一时间触发回调:
// 定义广播接收器 private final BroadcastReceiver mBleConnectReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device == null) return; if (BluetoothDevice.ACTION_ACL_CONNECTING.equals(action)) { // 此处即可捕获到设备发起的连接请求事件 Log.d(TAG, "收到设备连接请求:" + device.getAddress()); logs += "\n\n收到设备连接请求:" + device.getAddress(); updateHomeUI(); } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) { // 连接断开/连接失败,可额外获取错误码 int errorCode = intent.getIntExtra(BluetoothDevice.EXTRA_REASON, -1); Log.d(TAG, "连接断开/失败,错误码:" + errorCode + ",设备:" + device.getAddress()); } } };
在页面生命周期中注册/注销广播:
// onStart/onCreate 中注册广播,不要静态注册 IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTING); filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); registerReceiver(mBleConnectReceiver, filter); // onDestroy 中注销广播 @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(mBleConnectReceiver); }
2. 获取连接失败的具体原因
有两个位置可以拿到连接失败的错误码,对应转换为具体原因即可:
- 你现有的
onConnectionStateChange回调中,当status != BluetoothGatt.GATT_SUCCESS且newState == STATE_DISCONNECTED时,status的值就是GATT层返回的错误码,常见错误码对应关系:- 0:操作成功
- 8:连接超时
- 19:对端设备主动断开
- 22:本地主动断开
- 62:连接建立失败
- 133:通用未知错误,通常为蓝牙栈异常或设备兼容性问题
- 上述广播接收器的
ACTION_ACL_DISCONNECTED事件中,也可以通过intent.getIntExtra(BluetoothDevice.EXTRA_REASON, -1)拿到底层返回的错误原因码,可和GATT层错误码相互补充。
注意事项
- Android 12及以上版本需要提前申请
BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限,Android 11及以下需要申请ACCESS_FINE_LOCATION权限,否则无法正常接收广播和获取设备信息。 - 你原有代码里的
STATE_CONNECTING判断分支可以直接删除,不会触发。 - 确保你开启BLE广播时设置了
setConnectable(true),否则外设无法发起连接,你也收不到相关事件。
内容的提问来源于stack exchange,提问作者user5957595
相关产品推荐
相关产品推荐

