Android телефон как периферийные устройства
Я пытаюсь заставить nrf52 DK выступать в качестве центрального устройства и принимать уведомления о предупреждениях с устройства Android. Я использую в конце nrf пример стандартного уведомления о скандинавском оповещении, который должен уметь обрабатывать уведомления.
В android end я использую модифицированный пример blegatt, в который я также добавил части сервера gatt.
В настоящее время весь шебанг работает следующим образом: 1. nrf-доска рекламирует себя и сканирует телефон (на этом этапе роли традиционные, поскольку в nrf-плате нет пользовательского интерфейса). 2. Я открыл gattserver, создал alert_notification_service, добавил в него характеристики и добавил все в gattserver. 3. Я подключаюсь к плате nrf через обычное соединение gatt.
Я вижу, что сервис подключен платой, он пытается прочитать пару характеристик и написать дескриптор для одной. Однако уведомления (для целей тестирования я использую жестко закодированный контент для New Alert) не работают должным образом.
Вот вывод трассировки из терминала:
04-08 16:01:24.006 BluetoothLeScanner: onScanResult() - ScanResult{mDevice=CE:CE:67:C2:71:FE, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=Nordic_Alert_Notif.], mRssi=-35, mTimestampNanos=1475540620066358}
04-08 16:01:24.071 BluetoothAdapter: stopLeScan()
04-08 16:01:24.085 Timeline: Timeline: Activity_launch_request id:com.example.android.bluetoothlegatt time:98765127
04-08 16:01:24.105 BluetoothAdapter: stopLeScan()
04-08 16:01:24.106 BluetoothAdapter: scan not started yet
04-08 16:01:24.250 BluetoothGattServer: registerCallback()
04-08 16:01:24.250 BluetoothGattServer: registerCallback() - UUID=11b1f22d-460c-4b9a-82c4-aa176dac8a1c
04-08 16:01:24.252 BluetoothGattServer: onServerRegistered() - status=0 serverIf=9
04-08 16:01:24.253 BluetoothGattServer: addService() - service: 00001811-0000-1000-8000-00805f9b34fb
04-08 16:01:24.267 BluetoothLeService: Trying to create a new connection.
04-08 16:01:24.269 BluetoothGattServer: onServiceAdded() - service=00001811-0000-1000-8000-00805f9b34fbstatus=0
04-08 16:01:24.270 BluetoothGatt: connect() - device: CE:CE:67:C2:71:FE, auto: false
04-08 16:01:24.270 BluetoothGatt: registerApp()
04-08 16:01:24.270 BluetoothGatt: registerApp() - UUID=9f766219-eb65-4f92-aedd-22ec8d845d54
04-08 16:01:24.271 BluetoothLeService: onServiceAdded
04-08 16:01:24.272 BluetoothGatt: onClientRegistered() - status=0 clientIf=10
04-08 16:01:24.331 Timeline: Timeline: Activity_idle id: android.os.BinderProxy@3650f763 time:98765373
04-08 16:01:24.349 BluetoothGattServer: onServerConnectionState() - status=0 serverIf=6 device=CE:CE:67:C2:71:FE
04-08 16:01:24.349 BluetoothLeService: onConnectionStateChage device CE:CE:67:C2:71:FE
04-08 16:01:24.350 BluetoothGattServer: onServerConnectionState() - status=0 serverIf=8 device=CE:CE:67:C2:71:FE
04-08 16:01:24.350 BluetoothLeService: onConnectionStateChage device CE:CE:67:C2:71:FE
04-08 16:01:24.350 BluetoothGattServer: onServerConnectionState() - status=0 serverIf=9 device=CE:CE:67:C2:71:FE
04-08 16:01:24.350 BluetoothLeService: onConnectionStateChage device CE:CE:67:C2:71:FE
04-08 16:01:24.353 BluetoothGattServer: onServerConnectionState() - status=0 serverIf=7 device=CE:CE:67:C2:71:FE
04-08 16:01:24.353 BluetoothLeService: onConnectionStateChage device CE:CE:67:C2:71:FE
04-08 16:01:24.356 BluetoothGatt: onClientConnectionState() - status=0 clientIf=10 device=CE:CE:67:C2:71:FE
04-08 16:01:24.356 foo: onConnectionStateChange
04-08 16:01:24.356 foo: status connected
04-08 16:01:24.356 BluetoothGatt: discoverServices() - device: CE:CE:67:C2:71:FE
04-08 16:01:24.364 BluetoothGatt: onSearchComplete() = Device=CE:CE:67:C2:71:FE Status=0
04-08 16:01:24.364 foo: onServicesDiscovered
04-08 16:01:24.736 BluetoothLeService: onCharacteristicReadRequest UUID: 00002a47-0000-1000-8000-00805f9b34fb from device: CE:CE:67:C2:71:FE
04-08 16:01:24.833 BluetoothLeService: onCharacteristicReadRequest UUID: 00002a48-0000-1000-8000-00805f9b34fb from device: CE:CE:67:C2:71:FE
04-08 16:01:24.930 BluetoothLeService: ondescriptorwriterequest UUID: 00002902-0000-1000-8000-00805f9b34fbValue: 1
04-08 16:01:24.931 /BluetoothLeService: sending nofication!
Код:
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private BluetoothGattCharacteristic mSupportedNewAlertCategory;
private BluetoothGattCharacteristic mNewAlert;
private BluetoothGattCharacteristic mSupportedUnreadCategory;
private BluetoothGattCharacteristic mUnreadAlertStatus;
private BluetoothGattCharacteristic mAlertNotificationControlPoint;
private BluetoothDevice mBluetoothDevice;
private BluetoothGattServer mGattServer;
private BluetoothGattService mAlertNotificationService;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.d("foo", "onConnectionStateChange");
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.d("foo", "status connected");
gatt.discoverServices();
}
if (false) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.d("foo", "onServicesDiscovered");
if (status == BluetoothGatt.GATT_SUCCESS) {
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
Log.d(TAG, "setCharacterostisRead (GATT)");
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// This is special handling for the Heart Rate Measurement profile. Data parsing is
// carried out as per profile specifications:
// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* @return Return true if the initialization is successful.
*/
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
// BluetoothManager.
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
public BluetoothGattServerCallback serverCallback = new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
byte value[] = {0x03, 0x04, 0x52, 0x69, 0x63, 0x68, 0x61, 0x72, 0x64};
super.onConnectionStateChange(device, status, newState);
Log.d(TAG, "onConnectionStateChage device " + device.getAddress());
mNewAlert.setValue(value);
mGattServer.notifyCharacteristicChanged(mBluetoothDevice, mNewAlert, true);
}
@Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service);
mBluetoothGatt = mBluetoothDevice.connectGatt(getApplicationContext(), false, mGattCallback);
Log.d(TAG, "onServiceAdded");
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
Log.d(TAG, "onCharacteristicReadRequest UUID: " + characteristic.getUuid().toString() +" from device: " + device.getAddress());
if (characteristic.getUuid().equals(SampleGattAttributes.UUID_SUPPORTED_NEW_ALERT_CATEGORY)) {
byte value[] = {0x1f};
mSupportedNewAlertCategory.setValue(value);
mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, value);
} else if (characteristic.getUuid().equals(SampleGattAttributes.UUID_SUPPORTED_UNREAD_ALERT_CATEGORY)) {
byte value[] = {0x1f};
mSupportedUnreadCategory.setValue(value);
mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, value);
} else {
byte value[] = {0x03, 0x04, 0x52, 0x69, 0x63, 0x68, 0x61, 0x72, 0x64};
mNewAlert.setValue(value);
mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, value);
}
}
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
Log.d(TAG, "onCharacteristicwriterequest UUID: " + characteristic.getUuid().toString());
mGattServer.notifyCharacteristicChanged(mBluetoothDevice, characteristic, true);
}
@Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
Log.d(TAG, "ondescriptorReadrequest UUID: " + descriptor.getUuid().toString());
}
@Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
Log.d(TAG, "ondescriptorwriterequest UUID: " + descriptor.getUuid().toString() + "Value: " + value[0]);
if (value[0] == 1) {
Log.d(TAG, "sending nofication!");
mGattServer.notifyCharacteristicChanged(mBluetoothDevice, mNewAlert, true);
}
}
@Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
Log.d(TAG, "onNotificationSent");
}
};
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* @param address The device address of the destination device.
*
* @return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(address);
if (mBluetoothDevice == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
mGattServer = mBluetoothManager.openGattServer(this, serverCallback);
mSupportedNewAlertCategory = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_SUPPORTED_NEW_ALERT_CATEGORY, BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_READ);
mNewAlert = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_NEW_ALERT, BluetoothGattCharacteristic.FORMAT_UINT8 | BluetoothGattCharacteristic.PROPERTY_NOTIFY | BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ);
mSupportedUnreadCategory = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_SUPPORTED_UNREAD_ALERT_CATEGORY, BluetoothGattCharacteristic.PROPERTY_READ| BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_READ);
mUnreadAlertStatus = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_UNREAD_ALERT_STATUS, BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ);
mAlertNotificationControlPoint = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_ALERT_NOTIFICATION_CONTROL_POINT, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ);
mAlertNotificationControlPoint.setValue(new byte[]{0});
mAlertNotificationControlPoint.setValue(new byte[]{1});
mAlertNotificationControlPoint.setValue(new byte[]{4});
mAlertNotificationControlPoint.setValue(new byte[]{5});
BluetoothGattDescriptor clientCharacteristicConfig = new BluetoothGattDescriptor(SampleGattAttributes.UUID_CLIENT_CHARACTERISTIC_CONFIG, BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE);
clientCharacteristicConfig.setValue(new byte[]{1});
mNewAlert.addDescriptor(clientCharacteristicConfig);
mUnreadAlertStatus.addDescriptor(clientCharacteristicConfig);
mAlertNotificationService = new BluetoothGattService(SampleGattAttributes.UUID_ALERT_NOTIFICATION_SERVICE, BluetoothGattService.SERVICE_TYPE_PRIMARY);
mAlertNotificationService.addCharacteristic(mSupportedNewAlertCategory);
mAlertNotificationService.addCharacteristic(mNewAlert);
mAlertNotificationService.addCharacteristic(mSupportedUnreadCategory);
mAlertNotificationService.addCharacteristic(mUnreadAlertStatus);
mAlertNotificationService.addCharacteristic(mAlertNotificationControlPoint);
mGattServer.addService(mAlertNotificationService);
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
// mGattServer.connect(mBluetoothDevice, true);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
/**
* Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
* asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
* callback.
*
* @param characteristic The characteristic to read from.
*/
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
Log.d(TAG, "readCharacteristics (GATT)");
mBluetoothGatt.readCharacteristic(characteristic);
}
/**
* Enables or disables notification on a give characteristic.
*
* @param characteristic Characteristic to act on.
* @param enabled If true, enable notification. False otherwise.
*/
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
Log.d(TAG, "setCharacteristicNotification (GATT)");
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}
/**
* Retrieves a list of supported GATT services on the connected device. This should be
* invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
*
* @return A {@code List} of supported services.
*/
public List<BluetoothGattService> getSupportedGattServices() {
if (mBluetoothGatt == null) return null;
Log.d(TAG, "getSupportedServices (GATT)");
return mBluetoothGatt.getServices();
}
Проблема в том, что я не могу получать уведомления через mGattServer.sendResponse()- или.notifyCharacteristicChanged() -calls.
Не знаю, почему, похоже, нет примеров оповещений. Это довольно используемая функция, поэтому можно предположить, что есть множество примеров.
РЕДАКТИРОВАТЬ: Основная проблема заключалась в том, что у меня не было отдельных UUID для дескрипторов. Я добавил 00002902 для одного и 10002902 для второго. Также я удалил все вызовы уведомлений из обработки сервера и вместо этого поместил gattserver.sendresponse. После этого это работает.
2 ответа
Вы должны включить разрешение через дескриптор конфигурации клиента.
private BluetoothGatt mBluetoothGatt;
Blu
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
...etoothGattCharacteristic characteristic;
boolean enabled;
...
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
У меня была та же проблема, что и у вас, и я решил ее, задав характеристику для использования сервером в onServiceAdded()
@Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service);
serverCharacteristic =
service.getCharacteristic(UUID.fromString(SampleGattAttributes.FAN_OPERATING_STATE));
}
И когда я хочу отправить данные, я устанавливаю значение в этой характеристике с помощью setValue()
и уведомить об изменениях характеристики с notifyCharacteristicChanged()
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
byte[] mValue={0};
serverCharacteristic.setValue(mValue);
boolean confirm = mBluetoothGattServer.notifyCharacteristicChanged(device, serverCharacteristic , true);
Log.i("TEST","confirm:"+confirm);
}
Это работает для меня, надеюсь, это работает для вас
РЕДАКТИРОВАТЬ
Отправить данные без запроса:
public void sendData(byte[] data){
String uuidHRService = "xxxxx";
String uuidHRCharacteristic = "xxxxxxxx";
BluetoothGattService mBluetoothLeService = null;
BluetoothGattCharacteristic mBluetoothGattCharacteristic = null;
for (BluetoothGattService service : mBluetoothGatt.getServices()) {
if ((service == null) || (service.getUuid() == null)) {
Log.i("Test","Something is null");
continue;
}
if (uuidHRService.equalsIgnoreCase(service.getUuid().toString())) {
Log.i("Test","service.getUuid().toString()="+service.getUuid().toString());
mBluetoothLeService = service;
}
}
//BluetoothGattService mBluetoothLeService = mBluetoothGatt.getService(UUID.fromString(uuidHRService));
if(mBluetoothLeService!=null) {
mBluetoothGattCharacteristic =
mBluetoothLeService.getCharacteristic(UUID.fromString(uuidHRCharacteristic));
}
else{
Log.i("Test","mBluetoothLeService is null");
}
if(mBluetoothGattCharacteristic!=null) {
mBluetoothGattCharacteristic.setValue(data);
boolean write = mBluetoothGatt.writeCharacteristic(mBluetoothGattCharacteristic);
Log.i("Test","writeCharacteristic:"+write);
}
else{
Log.i("Test", "mBluetoothGattCharacteristic is null");
}
}
Не забудьте включить состояние уведомления вашего сервиса