Bon*_*i2k 68 android bluetooth bluetooth-lowenergy gatt android-4.3-jelly-bean
用于测试的设备:Nexus 4,Android 4.3
连接工作正常,但onCharacteristicChanged
我的回调方法永远不会被调用.但是我正在使用setCharacteristicNotification(char, true)
inside 注册通知onServicesDiscovered
,该函数甚至返回true.
设备日志(当通知应该出现/通过蓝牙设备发送时,实际上根本没有消息):
07-28 18:15:06.936 16777-16809/de.ffuf.leica.sketch D/BluetoothGatt: setCharacteristicNotification() - uuid: 3ab10101-f831-4395-b29d-570977d5bf94 enable: true
07-28 18:15:06.936 4372-7645/com.android.bluetooth D/BtGatt.GattService: registerForNotification() - address=C9:79:25:34:19:6C enable: true
07-28 18:15:06.936 4372-7645/com.android.bluetooth D/BtGatt.btif: btif_gattc_reg_for_notification
07-28 18:15:06.946 4372-7645/com.android.bluetooth D/BtGatt.btif: btgattc_handle_event: Event 1018
07-28 18:15:06.946 4372-7645/com.android.bluetooth D/BtGatt.GattService: onRegisterForNotifications() - address=null, status=0, registered=1, charUuid=3ab10101-f831-4395-b29d-570977d5bf94
07-28 18:15:06.946 4372-7645/com.android.bluetooth D/BtGatt.btif: btgattc_handle_event: Event 1016
07-28 18:15:06.946 4372-7645/com.android.bluetooth D/BtGatt.btif: btgattc_handle_event: Event 1018
07-28 18:15:06.946 4372-7645/com.android.bluetooth D/BtGatt.GattService: onRegisterForNotifications() - address=null, status=0, registered=1, charUuid=3ab10102-f831-4395-b29d-570977d5bf94
07-28 18:15:06.946 4372-7645/com.android.bluetooth D/BtGatt.btif: btgattc_handle_event: Event 1016
07-28 18:15:06.946 4372-7684/com.android.bluetooth E/bt-btif: already has a pending command!!
07-28 18:15:06.946 4372-7645/com.android.bluetooth D/BtGatt.btif: btgattc_handle_event: Event 1013
07-28 18:15:06.946 4372-7684/com.android.bluetooth E/bt-btif: already has a pending command!!
07-28 18:15:06.946 4372-7645/com.android.bluetooth D/BtGatt.btif: btgattc_handle_event: Event 1013
07-28 18:15:06.946 4372-7684/com.android.bluetooth E/bt-btif: already has a pending command!!
07-28 18:15:06.976 4372-7645/com.android.bluetooth D/BtGatt.btif: btif_gattc_upstreams_evt: Event 9
Run Code Online (Sandbox Code Playgroud)
GATT通知使用iOS工作正常,应用程序基本上与Android上相同(注册通知等).
有没有其他人经历过可能的解决方案?
One*_*rld 82
好像你忘了写Descriptor来告诉你的BLE设备进入这种模式.请参阅http://developer.android.com/guide/topics/connectivity/bluetooth-le.html#notification中处理描述符的代码行.
如果不设置此描述符,您将永远不会收到特征的更新.打电话setCharacteristicNotification
是不够的.这是一个常见的错误.
代码剪断
protected static final UUID CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
public boolean setCharacteristicNotification(BluetoothDevice device, UUID serviceUuid, UUID characteristicUuid,
boolean enable) {
if (IS_DEBUG)
Log.d(TAG, "setCharacteristicNotification(device=" + device.getName() + device.getAddress() + ", UUID="
+ characteristicUuid + ", enable=" + enable + " )");
BluetoothGatt gatt = mGattInstances.get(device.getAddress()); //I just hold the gatt instances I got from connect in this HashMap
BluetoothGattCharacteristic characteristic = gatt.getService(serviceUuid).getCharacteristic(characteristicUuid);
gatt.setCharacteristicNotification(characteristic, enable);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID);
descriptor.setValue(enable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : new byte[] { 0x00, 0x00 });
return gatt.writeDescriptor(descriptor); //descriptor write operation successfully started?
}
Run Code Online (Sandbox Code Playgroud)
小智 41
@ Boni2k - 我有同样的问题.就我而言,我有3个通知特性和少数读/写特性.
我发现的是writeGattDescriptor
和之间有一些依赖关系readCharacteristic
. 在发出任何readCharacteristic调用之前,所有 writeGattDescriptors 必须先完成并完成.
这是我使用的解决方案Queues
.现在我收到通知,其他一切正常:
像这样创建两个队列:
private Queue<BluetoothGattDescriptor> descriptorWriteQueue = new LinkedList<BluetoothGattDescriptor>();
private Queue<BluetoothGattCharacteristic> characteristicReadQueue = new LinkedList<BluetoothGattCharacteristic>();
Run Code Online (Sandbox Code Playgroud)
然后使用此方法在发现后立即编写所有描述符:
public void writeGattDescriptor(BluetoothGattDescriptor d){
//put the descriptor into the write queue
descriptorWriteQueue.add(d);
//if there is only 1 item in the queue, then write it. If more than 1, we handle asynchronously in the callback above
if(descriptorWriteQueue.size() == 1){
mBluetoothGatt.writeDescriptor(d);
}
}
Run Code Online (Sandbox Code Playgroud)
和这个回调:
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "Callback: Wrote GATT Descriptor successfully.");
}
else{
Log.d(TAG, "Callback: Error writing GATT Descriptor: "+ status);
}
descriptorWriteQueue.remove(); //pop the item that we just finishing writing
//if there is more to write, do it!
if(descriptorWriteQueue.size() > 0)
mBluetoothGatt.writeDescriptor(descriptorWriteQueue.element());
else if(readCharacteristicQueue.size() > 0)
mBluetoothGatt.readCharacteristic(readQueue.element());
};
Run Code Online (Sandbox Code Playgroud)
通常读取特征的方法如下:
public void readCharacteristic(String characteristicName) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
BluetoothGattService s = mBluetoothGatt.getService(UUID.fromString(kYourServiceUUIDString));
BluetoothGattCharacteristic c = s.getCharacteristic(UUID.fromString(characteristicName));
//put the characteristic into the read queue
readCharacteristicQueue.add(c);
//if there is only 1 item in the queue, then read it. If more than 1, we handle asynchronously in the callback above
//GIVE PRECEDENCE to descriptor writes. They must all finish first.
if((readCharacteristicQueue.size() == 1) && (descriptorWriteQueue.size() == 0))
mBluetoothGatt.readCharacteristic(c);
}
Run Code Online (Sandbox Code Playgroud)
和我读回调:
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
readCharacteristicQueue.remove();
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
else{
Log.d(TAG, "onCharacteristicRead error: " + status);
}
if(readCharacteristicQueue.size() > 0)
mBluetoothGatt.readCharacteristic(readCharacteristicQueue.element());
}
Run Code Online (Sandbox Code Playgroud)
小智 11
将值设置为描述符而不是put descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
,put descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)
.现在调用onCharacteristicChanged的回调.
小智 6
早期版本的Android接收通知(已注册的指示)中经验丰富的问题,之后总是有一个奇怪的断开连接事件.事实证明,这是因为我们注册了五个特征的通知.
在LogCat中发现的错误是:
02-05 16:14:24.990 1271-1601/? E/bt-btif? Max Notification Reached, registration failed.
Run Code Online (Sandbox Code Playgroud)
在4.4.2之前,注册数量上限为4!4.4.2将此限制增加到7.
通过减少早期版本中的注册数量,我们能够绕过这一限制.
我假设(你没有提供你的源代码)你没有像Google想要的那样实现它:
(1)
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
Run Code Online (Sandbox Code Playgroud)
然后
(2)
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
Run Code Online (Sandbox Code Playgroud)
我想2失踪了.在这种情况下,我相信将触发低级别通知,但它们永远不会报告给应用程序层.
归档时间: |
|
查看次数: |
74806 次 |
最近记录: |