这是我的代码,用于启用特征通知。
private void enableNotification(BluetoothGattCharacteristic characteristic) {
boolean s = bluetoothGatt.setCharacteristicNotification(characteristic, true);
Log.d(TAG, "enableNotification: setCharacteristicNotification " + s);
List descriptors = characteristic.getDescriptors();
if (null != descriptors && descriptors.size() > 0) {
for (BluetoothGattDescriptor descriptor : descriptors) {
Log.d(TAG, "enableNotification: " + descriptor.getUuid());
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
boolean s1 = bluetoothGatt.writeDescriptor(descriptor);
Log.d(TAG, "enableNotification: writeDescriptor " + s1);
}
} else {
Log.d(TAG, "enableNotification: descriptors is null");
}
}
以下是日志
BluetoothGatt: setCharacteristicNotification() - uuid: 00002a4d-0000-1000-8000-00805f9b34fb enable: true
BleService: enableNotification: setCharacteristicNotification true
BleService: enableNotification: 00002902-0000-1000-8000-00805f9b34fb
BleService: enableNotification: writeDescriptor true
BluetoothGatt: onConnectionUpdated() - Device=5C:B6:CC:00:1E:23 interval=40 latency=4 timeout=600 status=0
如我们所见, writeDescriptor返回true,但是onDescriptorWrite()方法未触发,并且BluetoothGatt显示了日志onConnectionUpdated()。 如果有人可以说出为什么我的通知没有触发器。 以下是我在BluetoothGattCallback中的onDescriptorWrite代码,如果执行该代码,无论如何都会有一些日志。
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "onDescriptorWrite: GATT_SUCCESS");
connectCallback.readMeterId();
} else if (status == BluetoothGatt.GATT_FAILURE) {
Log.d(TAG, "onDescriptorWrite: GATT_FAILURE");
} else {
Log.d(TAG, "onDescriptorWrite: something");
}
}
我的BluetoothGattCallback代码如下
private BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
bluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
gatt.close();
Log.d(TAG, "onConnectionStateChange: DISCONNECTED");
} else {
Log.d(TAG, "onConnectionStateChange: FAIL");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
//print all the service and characteristic
for (BluetoothGattService service : bluetoothGatt.getServices()) {
Log.d(TAG, "onServicesDiscovered: service ->" + service.getUuid());
for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
Log.d(TAG, "onServicesDiscovered: characteristic ->" + characteristic.getUuid());
}
}
BluetoothGattService service = bluetoothGatt.getService(UUID.fromString(BleConstant.SERVICE_UUID.SERVICE));
characteristics = service.getCharacteristics().subList(0, 2);
// enableNotification(characteristics.get(0));
for (BluetoothGattCharacteristic characteristic : characteristics) {
Log.d(TAG, "onServicesDiscovered: Properties -> " + characteristic.getUuid() + " " + characteristic.getProperties());
enableNotification(characteristic);
}
} else {
Log.d(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.d(TAG, "onCharacteristicChanged: " + Arrays.toString(characteristic.getValue()));
Log.d(TAG, "onCharacteristicChanged: string -> " + characteristic.getStringValue(0));
String callbackDataString = characteristic.getStringValue(0);
byte[] callbackDataByte = characteristic.getValue();
// boolean checkData = CRC16Util.getInstance().verification(callbackDataString);
dosomething with the response date
if (CRC16Util.getInstance().verification(callbackDataString)) {
connectCallback.crcError();
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.d(TAG, "onCharacteristicRead: " + Arrays.toString(characteristic.getValue()));
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.d(TAG, "onCharacteristicWrite: " + Arrays.toString(characteristic.getValue()));
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "onDescriptorWrite: GATT_SUCCESS");
connectCallback.readMeterId();
} else if (status == BluetoothGatt.GATT_FAILURE) {
Log.d(TAG, "onDescriptorWrite: GATT_FAILURE");
} else {
Log.d(TAG, "onDescriptorWrite: something");
}
}
};
在这段代码中connectCallback是一个像这样的接口
public interface ConnectCallback {
/**
* It needs to be triggered after notify successful
*/
void readMeterId();
/**
* callback of CRC ERROR
*/
void crcError();
/**
* callback of Transmission completed
*/
void onComplete();
/**
* callback of Read MeterId Error
*/
void onReadMeterIdError();
}
我仅在onDescriptorWrite成功(通知成功)时才向ble发送命令
以下是我的连接代码
public boolean connectToDevice(final String address, ConnectCallback connectCallback) {
if (null == bluetoothAdapter || null == address) {
Log.d(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
if (null != bluetoothGatt) {
bluetoothGatt = null;
}
final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.d(TAG, "Device not found. Unable to connect.");
return false;
}
Log.d(TAG, "Trying to create a new connection.");
this.connectCallback = connectCallback;
bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback);
return true;
}
我在Service中编写了所有ble代码,并在这样的活动中使用它
private void bindBleService() {
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
BleService.LocalBinder binder = (BleService.LocalBinder) service;
bleService = binder.getService();
if (!bleService.init()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
boolean isConn = bleService.connectToDevice(deviceAddress, new BleService.ConnectCallback() {
@Override
public void readMeterId() {
notifySuccess = true;
runOnUiThread(() -> {
waitBleDialog.setTitle(getString(R.string.edit_read_meter_id));
waitBleDialog.show();
});
bleService.sendDataToBle(READ_METER_ID.OCP);
meterIdUsed.put(READ_METER_ID.OCP, true);
}
@Override
public void crcError() {
if (waitBleDialog.isShowing()) {
waitBleDialog.cancel();
}
runOnUiThread(() -> {
Toast.makeText(BleResultActivity.this, getString(R.string.ble_crc_error), Toast.LENGTH_SHORT).show();
finish();
});
}
@Override
public void onComplete() {
if (recordList.size() == 0) {
if (waitBleDialog.isShowing()) {
waitBleDialog.cancel();
}
runOnUiThread(() -> Toast.makeText(BleResultActivity.this, getString(R.string.edit_no_new_record), Toast.LENGTH_SHORT).show());
recordTestButton.setOnClickListener(v -> runOnUiThread(() -> Toast.makeText(BleResultActivity.this, getString(R.string.edit_no_new_record), Toast.LENGTH_SHORT).show()));
} else {
runOnUiThread(() -> {
recordTestButton.setEnabled(true);
Toast.makeText(BleResultActivity.this, getString(R.string.edit_transmit_finish), Toast.LENGTH_SHORT).show();
});
recordTestButton.setOnClickListener(recordTest);
}
}
@Override
public void onReadMeterIdError() {
boolean haveCommendNotUsed = true;
for (String command : meterIdUsed.keySet()) {
Boolean commandUsed = meterIdUsed.get(command);
if (null == commandUsed) {
commandUsed = false;
}
if (!commandUsed) {
haveCommendNotUsed = true;
bleService.sendDataToBle(command);
meterIdUsed.put(command, true);
break;
} else {
haveCommendNotUsed = false;
}
}
if (!haveCommendNotUsed) {
waitBleDialog.cancel();
runOnUiThread(() -> Toast.makeText(BleResultActivity.this, getString(R.string.edit_read_meter_id_failed), Toast.LENGTH_SHORT).show());
finish();
}
}
});
if (!isConn) {
Log.d(TAG, "onServiceConnected: false");
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
bleService = null;
}
};
final Intent intent = new Intent(this, BleService.class);
bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE);
}
我现在所知道的是,运行enableNotification()方法并且writeDescriptor()返回true之后,发生了onConnectionUpdated()并失去了连接。 onConnectionUpdated()隐藏在源代码中,我不知道为什么会发生以及如何处理。