現(xiàn)象描述
調(diào)用 readCharacteristic
或者 writeCharacteristic
出現(xiàn)permission check failed! 時(shí), 后面便一直無法讀寫 characteristic
了状共。
原因分析
調(diào)用
readCharacteristic
方法后mDeviceBusy
被設(shè)置為true
/**
* Reads the requested characteristic from the associated remote device.
*
* <p>This is an asynchronous operation. The result of the read operation
* is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
* callback.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param characteristic Characteristic to read from the remote device
* @return true, if the read operation was initiated successfully
*/
public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) == 0) {
return false;
}
if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
if (mService == null || mClientIf == 0) return false;
BluetoothGattService service = characteristic.getService();
if (service == null) return false;
BluetoothDevice device = service.getDevice();
if (device == null) return false;
synchronized (mDeviceBusyLock) {
if (mDeviceBusy) return false;
mDeviceBusy = true;
}
try {
mService.readCharacteristic(mClientIf, device.getAddress(),
characteristic.getInstanceId(), AUTHENTICATION_NONE);
} catch (RemoteException e) {
Log.e(TAG, "", e);
mDeviceBusy = false;
return false;
}
return true;
}
正常情況盗蟆,成功發(fā)完數(shù)據(jù)后會有
onCharacteristicWrite
返回塘娶,并將mDeviceBusy
設(shè)置成false
鸥滨。
/**
* Characteristic has been written to the remote device.
* Let the app know how we did...
* @hide
*/
@Override
public void onCharacteristicWrite(String address, int status, int handle) {
if (VDBG) {
Log.d(TAG, "onCharacteristicWrite() - Device=" + address
+ " handle=" + handle + " Status=" + status);
}
if (!address.equals(mDevice.getAddress())) {
return;
}
synchronized (mDeviceBusyLock) {
mDeviceBusy = false;
}
BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice,
handle);
if (characteristic == null) return;
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|| status == GATT_INSUFFICIENT_ENCRYPTION)
&& (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
try {
final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
mService.writeCharacteristic(mClientIf, address, handle,
characteristic.getWriteType(), authReq,
characteristic.getValue());
mAuthRetryState++;
return;
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
runOrQueueCallback(new Runnable() {
@Override
public void run() {
final BluetoothGattCallback callback = mCallback;
if (callback != null) {
callback.onCharacteristicWrite(BluetoothGatt.this, characteristic,
status);
}
}
});
}
但是異常情況凡伊,當(dāng)
連接斷開
或者permissionCheck
失敗,不會去寫characteristic
,所以也就不會有onCharacteristicWrite
void writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq,
byte[] value) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (VDBG) {
Log.d(TAG, "writeCharacteristic() - address=" + address);
}
if (mReliableQueue.contains(address)) {
writeType = 3; // Prepared write
}
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
return;
}
if (!permissionCheck(connId, handle)) {
Log.w(TAG, "writeCharacteristic() - permission check failed!");
return;
}
gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value);
}
由于沒有收到
onCharacteristicWrite
導(dǎo)致mDeviceBusy
一直是true
,后面再發(fā)送其他請求尺借,都會報(bào)錯芯丧。