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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 00:22:33