我正在开发一个从 BLE 设备读取数据的 Android 应用程序。我在这里遇到了很多关于如何读取多个特征的解决方案,其中大多数都建议使用队列。
我确实实现了 Queue 方法,并且我的代码中的一切都按预期正常工作。我开始这个帖子的原因是为了找到最好、最有效的解决方案,并消除我对某些 BLE 服务特性如何工作的一些疑虑。
我将以下两个链接作为参考,这帮助我使我的代码正常工作。
来源1:
Android:BLE如何读取多个Characteristic? https://stackoverflow.com/questions/21278993/android-ble-how-to-read-multiple-characteristics
来源2:
Android BLE API:未收到 GATT 通知 https://stackoverflow.com/questions/17910322/android-ble-api-gatt-notification-not-received
我的要求是阅读心率测量 & 电池电量。最初,我尝试将心率和电池特性添加到队列中,然后为每个添加的元素调用读取/设置方法。
主要活动:
private void displayGattServices(List<BluetoothGattService> gattServices)
{
// get the required service & characteristics
................
................
// add the characteristics via Queue
hRM_characteristicReadQueue.add(characteristics);
// Initiate read/set methods
read_Characteristic();
};
private void read_Characteristic()
{
bluetoothHDPService.read(hRM_characteristicReadQueue.element());
bluetoothHDPService.set(hRM_characteristicReadQueue.element(),true);
hRM_characteristicReadQueue.remove();
};
蓝牙HDP服务:
public void read(BluetoothGattCharacteristic characteristic)
{
if (bluetoothAdapter == null || bluetoothGatt == null)
{
Log.w(TAG, "BluetoothAdapter not initialized");
return;
};
bluetoothGatt.readCharacteristic(characteristic);
};
public void set(BluetoothGattCharacteristic characteristic, boolean enabled)
{
if(bluetoothAdapter == null || bluetoothGatt == null)
{
Log.w(TAG, "BluetoothAdapter not initialized");
return;
};
bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_UUID);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
};
Back at 主要活动:(一旦读取特征BLE回调操作被触发)
我使用广播接收器来读取/设置下一个队列元素。
private final BroadcastReceiver gattUpdateReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
// TODO Auto-generated method stub
final String action = intent.getAction();
if (Service_HeartRateX_HDP.ACTION_GATT_CONNECTED.equals(action))
{
// Connection with the BLE device successful
................
................
}
else if (Service_HeartRateX_HDP.ACTION_GATT_DISCONNECTED.equals(action))
{
// BLE device is disconnected
................
................
}
else if (Service_HeartRateX_HDP.ACTION_GATT_SERVICES_DISCOVERED.equals(action))
{
displayGattServices(bluetoothHDPService.getSupportedGattServices());
}
else if (Service_HeartRateX_HDP.ACTION_DATA_AVAILABLE.equals(action))
{
Log.i(TAG, "Collecting data");
// Collecting the incoming data
displayData(intent.getStringExtra(Service_HeartRateX_HDP.HEART_DATA),
intent.getStringExtra(Service_HeartRateX_HDP.BATTERY_DATA));
if(hRM_characteristicReadQueue.size() > 0)
{
read_Characteristic();
};
};
};
};
上面的代码片段仅适用于一种特征(心率) BLE 设备继续发送心率测量数据,而对于其他特征 (电池百分比) BLE设备发送电池百分比数据仅一次。请注意,队列元素的顺序是首先读取/设置心率特征并将其从队列中删除,然后是电池特征。
最初,我认为队列没有按预期工作,并尝试交换队列中的特征顺序,其中电池百分比是第一个要读取/设置和删除的元素,然后是心率特征,以查看问题是否确实与不正确的相关编程。
但事实并非如此,因为 BLE 设备做了与之前相同的事情(继续发送心率测量数据,而电池百分比仅发送一次)。
因此,考虑到上述场景,我得出的结论是,需要每隔一段时间读取/设置电池电量百分比特征,以强制 BLE 设备发送其数据。下面的文章进一步帮助了这一点,其中一名开发人员必须使用计时器线程从 BLE 设备定期获取电池百分比更新。
如何在android中的ble中每5秒更新一次电池电量 https://stackoverflow.com/questions/23076353/how-to-update-the-battery-level-for-every-5seconds-in-ble-in-android
我不愿意在代码中使用计时器线程,因为这会使我已经很复杂的代码变得复杂无穷。然后我添加了以下条件read_Characteristic()方法来克服这个问题。
@ 主要活动
// where hrmBattery_Characteristics is a temporary variable which holds the
// battery characteristics
if(hRM_characteristicReadQueue.element() != hrmBattery_Characteristics)
{
hRM_characteristicReadQueue.remove();
};
通过这样做,电池特性永远不会从队列中删除,并且read_Characteristic()方法将通过广播接收器每隔一段时间调用一次(保持同步模式)。目前,这在我的代码中完美运行,但我需要专家的建议来确定这是否正确。
这个问题仅与电池有关还是与其他特性有关?幸运的是,到目前为止我只需要这两个特征的数据(心率测量数据和电池百分比)。
我没有尝试过两个以上的特性,因为我的 BLE 设备只有有限的一组特性,而这是目前其中仅有的两个特性。
这是因为 BLE 设备无法在给定的时间内向 Android 设备发送大数据包吗?原因是,即使上述代码运行良好,也从未出现过同时发送数据(心率和电池百分比)的情况。
如果有人能对此有所启发,我将不胜感激。
提前致谢!