下面列出了android.bluetooth.BluetoothGatt#writeCharacteristic ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void onExecute(@NonNull BluetoothGatt gatt) {
BluetoothGattCharacteristic c = extractCharacteristic(gatt);
if (c == null) {
postOnError(ErrorStrings.NO_CHARACTERISTIC);
return;
}
if (!c.setValue(data)) {
postOnError(ErrorStrings.VALUE_STORE_FAIL);
return;
}
if (!gatt.writeCharacteristic(c)) {
postOnError(ErrorStrings.WRITE_OP_INIT_FAIL);
}
}
public void authenticateConnection(BluetoothGatt bluetoothGatt) {
Log.i(TAG, "Trying to auth");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String receiverSn = prefs.getString("share_key", "SM00000000").toUpperCase();
if(bluetoothGatt != null) {
mBluetoothGatt = bluetoothGatt;
mShareService = mBluetoothGatt.getService(DexShareAttributes.CradleService);
if (mShareService != null) {
mAuthenticationCharacteristic = mShareService.getCharacteristic(DexShareAttributes.AuthenticationCode);
if(mAuthenticationCharacteristic != null) {
Log.i(TAG, "Auth Characteristic found: " + mAuthenticationCharacteristic.toString());
mAuthenticationCharacteristic.setValue((receiverSn + "000000").getBytes(StandardCharsets.US_ASCII));
currentGattTask = GATT_SETUP;
step = 1;
bluetoothGatt.writeCharacteristic(mAuthenticationCharacteristic);
} else {
Log.w(TAG, "Authentication Characteristic IS NULL");
}
} else {
Log.w(TAG, "CRADLE SERVICE IS NULL");
}
}
}
private void writeCharacteristic(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) throws DeviceDisconnectedException, DfuException,
UploadAbortedException {
gatt.writeCharacteristic(characteristic);
// We have to wait for confirmation
try {
synchronized (mLock) {
while ((!mRequestCompleted && mConnectionState == STATE_CONNECTED_AND_READY && mError == 0 && !mAborted) || mPaused) {
mLock.wait();
}
}
} catch (final InterruptedException e) {
loge("Sleeping interrupted", e);
}
if (mAborted) {
throw new UploadAbortedException();
}
}
/**
* Writes the buffer to the characteristic. The maximum size of the buffer is 20 bytes. This method is ASYNCHRONOUS and returns immediately after adding the data to TX queue.
*
* @param gatt the GATT device
* @param characteristic the characteristic to write to. Should be the DFU PACKET
* @param buffer the buffer with 1-20 bytes
* @param size the number of bytes from the buffer to send
*/
private void writePacket(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final byte[] buffer, final int size) {
byte[] locBuffer = buffer;
if (buffer.length != size) {
locBuffer = new byte[size];
System.arraycopy(buffer, 0, locBuffer, 0, size);
}
//logi("Sending Packet - " + bytesToHex(locBuffer));
characteristic.setValue(locBuffer);
gatt.writeCharacteristic(characteristic);
// FIXME BLE buffer overflow
// after writing to the device with WRITE_NO_RESPONSE property the onCharacteristicWrite callback is received immediately after writing data to a buffer.
// The real sending is much slower than adding to the buffer. This method does not return false if writing didn't succeed.. just the callback is not invoked.
//
// More info: this works fine on Nexus 5 (Android 4.4) (4.3 seconds) and on Samsung S4 (Android 4.3) (20 seconds) so this is a driver issue.
// Nexus 4 and 7 uses Qualcomm chip, Nexus 5 and Samsung uses Broadcom chips.
}
private synchronized void sendAuthRequestTxMessage(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.e(TAG, "Sending new AuthRequestTxMessage to " + getUUIDName(characteristic.getUuid()) + " ...");
authRequest = new AuthRequestTxMessage(getTokenSize());
Log.i(TAG, "AuthRequestTX: " + JoH.bytesToHex(authRequest.byteSequence));
characteristic.setValue(authRequest.byteSequence);
if (gatt != null) {
gatt.writeCharacteristic(characteristic);
} else {
Log.e(TAG, "Cannot send AuthRequestTx as supplied gatt is null!");
}
}
private synchronized void sendAuthRequestTxMessage(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.e(TAG, "Sending new AuthRequestTxMessage to " + getUUIDName(characteristic.getUuid()) + " ...");
authRequest = new AuthRequestTxMessage(getTokenSize());
Log.i(TAG, "AuthRequestTX: " + JoH.bytesToHex(authRequest.byteSequence));
characteristic.setValue(authRequest.byteSequence);
if (gatt != null) {
gatt.writeCharacteristic(characteristic);
} else {
Log.e(TAG, "Cannot send AuthRequestTx as supplied gatt is null!");
}
}
private boolean internalWriteCharacteristic(final BluetoothGattCharacteristic characteristic) {
final BluetoothGatt gatt = bluetoothGatt;
if (gatt == null || characteristic == null)
return false;
// Check characteristic property
final int properties = characteristic.getProperties();
if ((properties & (BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) == 0)
return false;
return gatt.writeCharacteristic(characteristic);
}
private synchronized void doVersionRequestMessage(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.d(TAG, "doVersionRequestMessage() start");
final VersionRequestTxMessage versionTx = new VersionRequestTxMessage();
characteristic.setValue(versionTx.byteSequence);
gatt.writeCharacteristic(characteristic);
Log.d(TAG, "doVersionRequestMessage() finished");
}
public static boolean writeCharacteristic(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int value, int format, int offset) {
if (gatt == null) {
return false;
}
Timber.d("prop: %02x", characteristic.getProperties());
characteristic.setValue(value, format, offset);
return gatt.writeCharacteristic(characteristic);
}
private void writeCharacteristicOADIdentify(BluetoothGatt gatt) {
BluetoothGattService oads = gatt.getService(Constants.UUID_OAD_SERVICE);
BluetoothGattCharacteristic iden = oads.getCharacteristic(Constants.UUID_OAD_CHAR_IDENTIFY);
byte[] zeros = new byte[2];
zeros[0] = 0;
zeros[1] = 0;
iden.setValue(zeros);
if (!gatt.writeCharacteristic(iden)) {
Log.e(TAG, "FAILURE: Write char OAD Identify 0x0000");
fail("FAILURE: Write char OAD Identify 0x0000");
}
Log.i(TAG, "SUCCESS: Wrote characteristic");
}
/**
* Writes the operation code to the characteristic. This method is SYNCHRONOUS and wait until the
* {@link android.bluetooth.BluetoothGattCallback#onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} will be called or the connection state will change from {@link #STATE_CONNECTED_AND_READY}.
* If connection state will change, or an error will occur, an exception will be thrown.
*
* @param gatt the GATT device
* @param characteristic the characteristic to write to. Should be the DFU CONTROL POINT
* @param value the value to write to the characteristic
* @param reset whether the command trigger restarting the device
* @throws DeviceDisconnectedException
* @throws DfuException
* @throws UploadAbortedException
*/
private void writeOpCode(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final byte[] value, final boolean reset) throws DeviceDisconnectedException, DfuException,
UploadAbortedException {
mReceivedData = null;
mError = 0;
mRequestCompleted = false;
/*
* Sending a command that will make the DFU target to reboot may cause an error 133 (0x85 - Gatt Error). If so, with this flag set, the error will not be shown to the user
* as the peripheral is disconnected anyway. See: mGattCallback#onCharacteristicWrite(...) method
*/
mResetRequestSent = reset;
characteristic.setValue(value);
sendLogBroadcast(LOG_LEVEL_VERBOSE, "Writing to characteristic " + characteristic.getUuid());
sendLogBroadcast(LOG_LEVEL_DEBUG, "gatt.writeCharacteristic(" + characteristic.getUuid() + ")");
gatt.writeCharacteristic(characteristic);
// We have to wait for confirmation
try {
synchronized (mLock) {
while ((!mRequestCompleted && mConnectionState == STATE_CONNECTED_AND_READY && mError == 0 && !mAborted) || mPaused)
mLock.wait();
}
} catch (final InterruptedException e) {
loge("Sleeping interrupted", e);
}
if (mAborted)
throw new UploadAbortedException();
if (!mResetRequestSent && mError != 0)
throw new DfuException("Unable to write Op Code " + value[0], mError);
if (!mResetRequestSent && mConnectionState != STATE_CONNECTED_AND_READY)
throw new DeviceDisconnectedException("Unable to write Op Code " + value[0], mConnectionState);
}
/**
* Write data to characteristic, and send to remote bluetooth le device.
*
* @param address The address to read from.
* @param serviceUUID remote device service uuid
* @param characteristicUUID remote device characteristic uuid
* @param value Send to remote ble device data.
* @return if write success return true
*/
public boolean writeCharacteristic(String address, String serviceUUID,
String characteristicUUID, String value) {
BluetoothGatt bluetoothGatt = mBluetoothGattMap.get(address);
if (bluetoothGatt != null) {
BluetoothGattService service =
bluetoothGatt.getService(UUID.fromString(serviceUUID));
BluetoothGattCharacteristic characteristic =
service.getCharacteristic(UUID.fromString(characteristicUUID));
characteristic.setValue(value);
return bluetoothGatt.writeCharacteristic(characteristic);
}
return false;
}
private synchronized void doVersionRequestMessage(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.d(TAG, "doVersionRequestMessage() start");
final VersionRequestTxMessage versionTx = new VersionRequestTxMessage();
characteristic.setValue(versionTx.byteSequence);
gatt.writeCharacteristic(characteristic);
Log.d(TAG, "doVersionRequestMessage() finished");
}
/**
* Writes the Init packet to the characteristic. This method is SYNCHRONOUS and wait until the {@link android.bluetooth.BluetoothGattCallback#onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
* will be called or the connection state will change from {@link #STATE_CONNECTED_AND_READY}. If connection state will change, or an error will occur, an exception will be thrown.
*
* @param gatt the GATT device
* @param characteristic the characteristic to write to. Should be the DFU PACKET
* @param buffer the init packet as a byte array. This must be shorter or equal to 20 bytes (TODO check this restriction).
* @param size the init packet size
* @throws DeviceDisconnectedException
* @throws DfuException
* @throws UploadAbortedException
*/
private void writeInitPacket(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final byte[] buffer, final int size) throws DeviceDisconnectedException, DfuException,
UploadAbortedException {
byte[] locBuffer = buffer;
if (buffer.length != size) {
locBuffer = new byte[size];
System.arraycopy(buffer, 0, locBuffer, 0, size);
}
mReceivedData = null;
mError = 0;
mInitPacketSent = false;
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
characteristic.setValue(locBuffer);
logi("Sending init packet (Value = " + parse(locBuffer) + ")");
sendLogBroadcast(LOG_LEVEL_VERBOSE, "Writing to characteristic " + characteristic.getUuid());
sendLogBroadcast(LOG_LEVEL_DEBUG, "gatt.writeCharacteristic(" + characteristic.getUuid() + ")");
gatt.writeCharacteristic(characteristic);
// We have to wait for confirmation
try {
synchronized (mLock) {
while ((!mInitPacketSent && mConnectionState == STATE_CONNECTED_AND_READY && mError == 0 && !mAborted) || mPaused)
mLock.wait();
}
} catch (final InterruptedException e) {
loge("Sleeping interrupted", e);
}
if (mAborted)
throw new UploadAbortedException();
if (mError != 0)
throw new DfuException("Unable to write Init DFU Parameters", mError);
if (mConnectionState != STATE_CONNECTED_AND_READY)
throw new DeviceDisconnectedException("Unable to write Init DFU Parameters", mConnectionState);
}
private synchronized void sendAuthRequestTxMessage(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.e(TAG, "Sending new AuthRequestTxMessage to " + getUUIDName(characteristic.getUuid()) + " ...");
authRequest = new AuthRequestTxMessage(getTokenSize());
Log.i(TAG, "AuthRequestTX: " + JoH.bytesToHex(authRequest.byteSequence));
characteristic.setValue(authRequest.byteSequence);
if (gatt != null) {
gatt.writeCharacteristic(characteristic);
} else {
Log.e(TAG, "Cannot send AuthRequestTx as supplied gatt is null!");
}
}
private synchronized void sendAuthRequestTxMessage(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.e(TAG, "Sending new AuthRequestTxMessage to " + getUUIDName(characteristic.getUuid()) + " ...");
authRequest = new AuthRequestTxMessage(getTokenSize());
Log.i(TAG, "AuthRequestTX: " + JoH.bytesToHex(authRequest.byteSequence));
characteristic.setValue(authRequest.byteSequence);
if (gatt != null) {
gatt.writeCharacteristic(characteristic);
} else {
Log.e(TAG, "Cannot send AuthRequestTx as supplied gatt is null!");
}
}
private synchronized void doVersionRequestMessage(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.d(TAG, "doVersionRequestMessage() start");
final VersionRequestTxMessage versionTx = new VersionRequestTxMessage();
characteristic.setValue(versionTx.byteSequence);
gatt.writeCharacteristic(characteristic);
Log.d(TAG, "doVersionRequestMessage() finished");
}
public static boolean writeCharacteristic(BluetoothGatt gatt, UUID serviceUuid, UUID characteristicUuid, byte[] value) {
if (gatt == null) {
return false;
}
BluetoothGattCharacteristic characteristic = gatt.getService(serviceUuid).getCharacteristic(characteristicUuid);
boolean submitted = characteristic.setValue(value);
Timber.d("submitted: %s", submitted);
return gatt.writeCharacteristic(characteristic);
}
private synchronized void doBatteryInfoRequestMessage(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.d(TAG, "doBatteryInfoMessage() start");
characteristic.setValue(new BatteryInfoTxMessage().byteSequence);
gatt.writeCharacteristic(characteristic);
Log.d(TAG, "doBatteryInfoMessage() finished");
}
@Override
public void write(final BleDevice device, String serviceUuid, String writeUuid, byte[] data, final BleWriteCallback callback) {
checkNotNull(callback, BleWriteCallback.class);
if (data == null || data.length < 1 || data.length > 509) {
callback.onFailure(BleCallback.FAIL_OTHER, data == null ? "data is null" :
"data length must range from 1 to 509", device);
return;
}
if (data.length > 20) {
Logger.w("data length is greater than the default(20 bytes), make sure MTU >= " + (data.length + 3));
}
if (!checkConnection(device, callback)) {
return;
}
BluetoothGatt gatt = mGattMap.get(device.address);
if (!checkUuid(serviceUuid, writeUuid, gatt, device, callback)) {
return;
}
OperationIdentify identify = getOperationIdentifyFromMap(mWriteCallbackMap, device.address, serviceUuid, writeUuid);
if (identify != null) {
mWriteCallbackMap.put(identify, callback);
} else {
mWriteCallbackMap.put(new OperationIdentify(device.address, serviceUuid, writeUuid), callback);
}
BluetoothGattService service = gatt.getService(UUID.fromString(serviceUuid));
BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(writeUuid));
boolean writable = (characteristic.getProperties() & (BluetoothGattCharacteristic.PROPERTY_WRITE |
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) > 0;
if (!writable) {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure(BleCallback.FAIL_OTHER, "the characteristic is not writable", device);
}
});
return;
}
if (!characteristic.setValue(data) || !gatt.writeCharacteristic(characteristic)) {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure(BleCallback.FAIL_OTHER, "write fail because of unknown reason", device);
}
});
}
}