You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 13以下设备中BluetoothGattCallback的onCharacteristicChanged无法触发

Android 11上BluetoothGattCallback的onCharacteristicChanged无法触发,Android 13正常

我尝试通过BLE设备接收数据,仅在Android 13上正常工作,Android 11设备中BluetoothGattCallback的onCharacteristicChanged方法无法触发。

配置代码

@SuppressLint("MissingPermission")
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
    bluetoothGatt.requestMtu(517)
}

override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) {
    val characteristic = findCharacteristics()
    enableNotification(characteristic)
}

fun ByteArray.toHexString(): String =
    joinToString(separator = "", prefix = "") { String.format("%02X", it) }

override fun onCharacteristicChanged(
    gatt: BluetoothGatt,
    characteristic: BluetoothGattCharacteristic,
    value: ByteArray
) {
    Log.d("CHAR", value.toHexString())
}

权限检查逻辑

private fun checkPermissions() {
    when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            requestPermissions.launch(
                arrayOf(
                    Manifest.permission.BLUETOOTH_SCAN,
                    Manifest.permission.BLUETOOTH_CONNECT
                )
            )
        }
        Build.VERSION.SDK_INT < Build.VERSION_CODES.S -> {
            requestPermissions.launch(
                arrayOf(
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                )
            )
        }
    }
}

private val requestPermissions =
    registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
        permissions.forEach { (key, value) ->
            when (key) {
                Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION -> {
                    if (!value) {
                        ActivityCompat.requestPermissions(
                            requireActivity(),
                            arrayOf(
                                Manifest.permission.ACCESS_COARSE_LOCATION,
                                Manifest.permission.ACCESS_FINE_LOCATION
                            ),
                            1
                        )
                    }
                }
                Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT -> {
                    if (!value) {
                        ActivityCompat.requestPermissions(
                            requireActivity(),
                            arrayOf(
                                Manifest.permission.BLUETOOTH_SCAN,
                                Manifest.permission.BLUETOOTH_CONNECT
                            ),
                            1
                        )
                    }
                }
            }
        }
    }

Android 11上的运行日志

D/BluetoothGatt: onConnectionUpdated() - Device=7C:9E:BD:07:3D:82 interval=6 latency=0 timeout=500 status=0
D/BluetoothGatt: onSearchComplete() = Device=7C:9E:BD:07:3D:82 Status=0
D/BluetoothGatt: configureMTU() - device: 7C:9E:BD:07:3D:82 mtu: 517
D/BluetoothGatt: onConfigureMTU() - Device=7C:9E:BD:07:3D:82 mtu=517 status=0
D/BluetoothGatt: setCharacteristicNotification() - uuid: 00001103-0000-1000-8000-00805f9b34fb enable: true

排查与解决方向

  • 补全权限声明:Android 11除了位置权限,需在Manifest中添加正常权限:

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    

    同时确保设备位置服务处于开启状态,Android 11中BLE通知依赖位置服务,仅授予权限但关闭位置会导致接收异常。

  • 完善通知配置:仅调用setCharacteristicNotification不够,必须配置客户端特征描述符(CCCD),检查enableNotification实现:

    @SuppressLint("MissingPermission")
    fun enableNotification(characteristic: BluetoothGattCharacteristic) {
        bluetoothGatt.setCharacteristicNotification(characteristic, true)
        val cccdUuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
        val descriptor = characteristic.getDescriptor(cccdUuid) ?: return
        descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
        bluetoothGatt.writeDescriptor(descriptor)
    }
    

    可通过onDescriptorWrite回调确认描述符写入是否成功。

  • 验证特征有效性:在onMtuChanged中打印characteristic的UUID,确认findCharacteristics()确实找到了目标特征,同时检查该特征是否具备PROPERTY_NOTIFY或PROPERTY_INDICATE属性。

  • 处理系统缓存异常:重启设备蓝牙,或清除应用的蓝牙缓存,部分Android 11设备存在蓝牙服务缓存问题导致通知失效。


内容的提问来源于stack exchange,提问作者Helvio Siqueira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:37:21