Android应用无法接收BLE体温计FORA IR42的温度指示数据
解决FORA IR42 BLE体温计温度指示数据不触发
onCharacteristicChanged的方案 一、确认服务与特征的正确性
- 用BLE调试工具(如nRF Connect)扫描FORA IR42,验证温度服务UUID是否为
00001809-0000-1000-8000-00805f9b34fb,测量特征UUID是否为00002a1c-0000-1000-8000-00805f9b34fb。部分设备可能使用自定义UUID,这一步必须验证。 - 检查特征属性:确保目标特征具备INDICATE或NOTIFY属性,无此属性则无法接收主动推送的数据。
二、修复权限请求逻辑
当前权限请求是逐个检查返回,可能导致未完成授权就执行BLE连接。修改为一次性请求所有必要权限,授权完成后再连接:
private val REQUIRED_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { arrayOf( Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.ACCESS_FINE_LOCATION ) } else { arrayOf( Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH, Manifest.permission.ACCESS_FINE_LOCATION ) } private fun checkPermissions() { val missingPermissions = REQUIRED_PERMISSIONS.filter { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED } if (missingPermissions.isNotEmpty()) { ActivityCompat.requestPermissions(this, missingPermissions.toTypedArray(), 100) } else { connectToThermometer() } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == 100) { val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED } if (allGranted) { connectToThermometer() } } } private fun connectToThermometer() { val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() for (device in bluetoothAdapter.bondedDevices) { if (device.name.startsWith("F")) { gatt = device.connectGatt(this, false, gattCallback) break } } }
同时在Manifest中优化Android 12+权限配置:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
三、完善BluetoothGattCallback实现
- 同时重写新旧版
onCharacteristicChanged:Android 13新增了带value参数的重载,但部分设备仍调用旧版方法,需同时实现:
override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { super.onCharacteristicChanged(gatt, characteristic) val value = characteristic.value processTemperatureData(value) gatt.sendConfirmation(characteristic) } override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray) { super.onCharacteristicChanged(gatt, characteristic, value) processTemperatureData(value) gatt.sendConfirmation(characteristic) } private fun processTemperatureData(value: ByteArray) { if (value.size >= 2) { val temperature = ((value[1].toInt() and 0xFF) shl 8) or (value[0].toInt() and 0xFF) val celsiusTemperature = temperature / 10.0 Log.i("callback", "Temperature: $celsiusTemperature °C") } }
- 发送指示确认:若设备使用INDICATION模式,必须发送确认,否则设备可能停止推送数据。
- 增强descriptor写入校验:在
onDescriptorWrite中处理写入失败的情况:
override fun onDescriptorWrite(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) { super.onDescriptorWrite(gatt, descriptor, status) if (status == BluetoothGatt.GATT_SUCCESS) { Log.i("callback", "Descriptor write success") } else { Log.e("callback", "Descriptor write failed, status: $status") descriptor?.let { gatt?.writeDescriptor(it) } } }
四、验证设备触发条件
FORA IR42仅在完成测量后才会发送温度数据,测试时需确保设备已完成一次体温测量(按下测量键并完成读取)。
五、优化GATT连接参数
尝试将connectGatt的autoConnect参数设为true,部分设备在自动连接模式下稳定性更好:
gatt = device.connectGatt(this, true, gattCallback)
内容的提问来源于stack exchange,提问作者Sakthivel C
相关产品推荐
相关产品推荐

