我在我的应用中使用BLE连接。我有一个单独的蓝牙功能类,我从一个不同的片段类传递一个命令来写任何值。
因此,基于场景,在片段内部,单击按钮将向蓝牙类发送写入命令。它在第一次工作正常,我得到了回应。但是第二次单击按钮时,onCharacteristicChanged()被调用两次,第三次单击使其被调用三次,依此类推。我真的无法弄明白。我将在下面发布我的代码。请看一看。如有任何疑问,请告诉我。提前谢谢。
我在OnDescriptorWrite()中写入数据,其中收集数据 onCharacteristicChanged()。
片段内:
rvw_availableList.addOnItemTouchListener((
new RecyclerItemClickListener(myContext, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position)
{
BluetoothDevice bl_device = al_deviceList.get(position);
bleUtil.writeData(bl_device,"3AxxxxxxD");
}
})
));
现在在BleUtil Class的writeData()中:
public void writeData(BluetoothDevice bluetoothDevice, final String value)
{
BluetoothGattCallback gattCallback =
new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
gatt.discoverServices();
}
@Override
public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
activity.runOnUiThread(new Runnable() {
public void run() {
// prgd_progress.HideProgressDialog();
Log.d("onServicesDiscovered", "Service uuid ");
List<BluetoothGattService> gattServices = gatt.getServices();
Log.d("onServicesDiscovered", "Services count: "+gattServices.size());
for (BluetoothGattService gattService: gattServices)
{
Log.d("aniservice",gattService.getUuid().toString());
}
if (status == BluetoothGatt.GATT_SUCCESS) {
ArrayList<String> alst_uuid = new ArrayList<String>();
BluetoothGattCharacteristic characteristic =
gatt.getService(UUID.fromString(SERVICE_ID)).getCharacteristics().get(0);
Log.d("anicheck",characteristic.getUuid().toString());
Log.d("anicheck",characteristic.getDescriptors().get(0).getUuid().toString());
// BluetoothGattCharacteristic characteristic =
// gattServices.get(0).getCharacteristics().get(0);
// Log.d("foundoutchar",gattServices.get(0).getUuid()+" "+gattServices.get(0).getCharacteristics().get(0).getUuid()+"");
gatt.setCharacteristicNotification(characteristic,true);
for (BluetoothGattDescriptor descriptor:characteristic.getDescriptors()){
Log.e("anicheck", "BluetoothGattDescriptor: "+descriptor.getUuid().toString());
}
final BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
if(descriptor!= null)
{
descriptor.setValue(
BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
else
{
Toast.makeText(activity,"nullval", Toast.LENGTH_SHORT).show();
}
// Log.d("foundoutchar", descriptor.getUuid().toString());
}
}
});
}
@Override
public void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
activity.runOnUiThread(new Runnable() {
public void run()
{
}
});
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, int status)
{
Log.d("onCharacteristicread",characteristic.getValue().toString());
Log.d("onCharacteristicread","called");
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] charValue = characteristic.getValue();
final String str_result = bytesToHex(charValue);
Log.d("onCharacteristicfullres",str_result);
final Intent intent = new Intent("ble_data"); //FILTER is a string to identify this intent
intent.putExtra("val", "getdeviceinfo");
intent.putExtra("data", str_result);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
activity.runOnUiThread(new Runnable() {
public void run()
{
// byte[] charValue = characteristic.getValue();
// String str_result = bytesToHex(charValue);
// Log.d("onCharacteristicfullres",str_result);
//Toast.makeText(activity, "On char changed "+str_result, Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onDescriptorWrite(final BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
{
activity.runOnUiThread(new Runnable() {
public void run()
{
Log.d("oncharadesc","abcd");
// prgd_progress.HideProgressDialog();
BluetoothGattService service = gatt.getService(UUID.fromString(SERVICE_ID));
for (BluetoothGattCharacteristic characteristics: service.getCharacteristics())
{
Log.d("getit",characteristics.getUuid().toString());
}
final BluetoothGattCharacteristic characteristic =
gatt.getService(UUID.fromString(SERVICE_ID)).getCharacteristics().get(0);
byte[] byt_arr;
byt_arr = hexStringToByteArray(value);
characteristic.setValue(byt_arr);
gatt.writeCharacteristic(characteristic);
}
});
}
};
BluetoothGatt bluetoothGatt = bluetoothDevice.connectGatt(activity, true, gattCallback);
}
答案 0 :(得分:2)
这是因为您多次调用connectGatt。每次调用connectGatt时,都会创建一个侦听通知的GATT客户端对象。因此,在三次按下之后,您将有三个GATT客户端,它们都处理每个通知。
您应该更改代码,以便在编写数据时使用以前创建的GATT客户端。
答案 1 :(得分:1)
首先,如其他答案中所述,您不应创建BluetoothGattCallback
的多个实例,而应以它们作为每个设备的单个实体存在的方式实现它们,例如,将这些对象保存在HashMap中或类似的东西。我还想添加检查,如果您从ble收到繁忙状态。发生在某些ble上,它们为单次写入通知两次通知,第一个响应表示忙状态,其他则给我们数据,这完全取决于设备之间的情况。因此,也请对ble的行为进行一些检查。
答案 2 :(得分:0)
我同意埃米尔的观点。首先尝试建立连接,如果连接成功,请尝试将某些内容写入特征或描述符。另请注意,在方法writeData()中不断创建BluetoothGattCallback,需要为每个连接的设备创建一次,并且需要缓存onServicesDiscovered()方法的结果,以免不断引起它。