After subscribe notification immediate write command doesn't work. I have to restart server device and auto connect to existing ble instance to get result.
Notification enable code:
public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return false;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
System.out.println("descriptor length----" + characteristic.getDescriptors().size());
// This is specific to Heart Rate Measurement.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
System.out.println("descriptor--" + Arrays.toString(descriptor.getValue()));
System.out.println("characteristic value--" + Arrays.toString(descriptor.getCharacteristic().getValue()));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
return mBluetoothGatt.writeDescriptor(descriptor);
}
return false;
}
and here is my write command code:
public void writeCustomCharacteristic(String value) {
this.value = "";
this.command = value;
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
/*check if the service is available on the device*/
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("65333333-a115-11e2-9e9a-0800200ca100"));
if (mCustomService == null) {
Log.w(TAG, "Custom BLE Service not found");
return;
}
/*get the read characteristic from the service*/
BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString("65333333-a115-11e2-9e9a-0800200ca101"));
mWriteCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
mWriteCharacteristic.setValue(value.getBytes());
if (!mBluetoothGatt.writeCharacteristic(mWriteCharacteristic)) {
Log.w(TAG, "Failed to write characteristic");
}
System.out.println("BluetoothLeService.writeCustomCharacteristic------->" + value);
}
Before write any characteristic , delay for few sec . Bcz it takes time to execute.
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
mBluetoothGatt.writeDescriptor(RTS_CCCD); //for descriptor
// or
mBluetoothGatt.readCharacteristic(brspInfo); //for read
//or
mBluetoothGatt.writeCharacteristic(brspInfo); //for write
}
}, 500);
Here you get more explaination
Related
I am using Android 4.4.2 on Moto X. I have a custom bluetooth low energy board, which has a red LED turned on when no devices connected to it. It supports just one connected device at a time. I am building an Android application that tries to connect to this BLE device and writes to its characteristic and then disconnects from it. I am having two problems: after writing a value to characteristic, I am doing:
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
mBluetoothGatt = null;
mBluetoothAdapter.cancelDiscovery();
broadcastUpdate(ACTION_GATT_DISCONNECTED);
but that doesn't actually disconnect my smartphone (the LED on BLE device remains turned off, meaning that some device is still connected to it). However, when I turn off the bluetooth adapter on my smartphone, the LED immediately turns on.
The second problem is that I can't write to my characteristic from the first attempt, I have to call the same sequence for the second time.
Here's the procedure that is called to write my characterictic:
public void trytounlock() {
Context context = getApplicationContext();
if (connect("E2:0C:B9:4D:B9:56"))
{
Log.w(TAG, "connect returned true!");
}
else {
Log.w(TAG, "connect returned false - warum?");
};
if (mBluetoothAdapter == null ) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
else
{
Log.w(TAG, "BluetoothAdapter initialized successfully!");
}
if ( mBluetoothGatt == null) {
Log.w(TAG, "GATT not initialized");
return;
}
else
{
Log.w(TAG, "GATT initialized succesfully!");
}
/*check if the service is available on the device*/
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("0000f00d-1212-efde-1523-785fef13d123"));
while (!mBluetoothGatt.discoverServices())
{
Log.w(TAG, "Waiting for service discovery");
}
int duration = Toast.LENGTH_SHORT;
if(mCustomService == null){
Log.w(TAG, "Custom BLE Service not found here. ");
return;
}
else
{
Log.w(TAG, "Custom BLE Service found successfully!");
}
BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString("0000beef-1212-efde-1523-785fef13d123"));
byte[] raw={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
mWriteCharacteristic.setValue(raw);
if(mBluetoothGatt.writeCharacteristic(mWriteCharacteristic) == false){
Log.w(TAG, "Failed to write characteristic");
Toast.makeText(context, "Failed to write characteristic - ошибочка!!", duration).show();
}
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized, while trying to disconnect - weird!!!");
}
else {
mBluetoothGatt.disconnect();
}
mWriteCharacteristic = null;
mCustomService = null;
if (mBluetoothGatt == null) {
}
else {
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
mBluetoothGatt = null;
mBluetoothAdapter.cancelDiscovery();
}
broadcastUpdate(ACTION_GATT_DISCONNECTED);
}
Here's my connect procedure:
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
// 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) {
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) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
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);
}
So, the questions are:
How to release my board properly, so that is sees no other devices connected to it?
What is the reason it only write my characteristic, when I call it for the second time after I initially turn on the bluetooth adapter?
after the connection is established I want to read the value from the characteristic and save the value in a byte array.
Here is my function for the reading inside my BluetoothLeService:
public byte[] readWhiteAndIntensityCharacteristic() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return null;
}
/*check if the service is available on the device*/
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString(UuidAdresssService));
if (mCustomService == null) {
Log.w(TAG, "Custom BLE Service not found");
return null;
}
/*get the read characteristic from the service*/
BluetoothGattCharacteristic mReadCharacteristic = mCustomService.getCharacteristic(UUID.fromString(UuidAdresssWhiteAndIntensityCharastic));
byte[] messageByte = mReadCharacteristic.getValue();
if (messageByte != null && messageByte.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(messageByte.length);
for (byte byteChar : messageByte)
stringBuilder.append(String.format("%02X", byteChar));
s = "0x" + stringBuilder.toString();
Log.v("Scan Activity", s);
if (mBluetoothGatt.readCharacteristic(mReadCharacteristic) == false) {
Log.w(TAG, "Failed to read characteristic");
}
}
return messageByte;
}
This function get called inside my DeviceControlActivity:
public void getStartUpValue(){
Log.w(TAG, "Reading completed");}
if(mBluetoothLeService.readWhiteAndIntensityCharacteristic() == null)
{
Log.w(TAG, "FAILED Reading value failed");
}
startValue = mBluetoothLeService.readWhiteAndIntensityCharacteristic();
Log.w(TAG, "Reading completed");
}
I call the getStartUpValue function after the connection is established.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
mBluetoothLeService.getSupportedGattServices();
getStartUpValue();
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
The reading is failing everytime but sending values to the characteristic is no problem.
How can I fix this problem?
The solution is: mBluetoothGatt.readCharacteristic(mReadCharacteristic)
After the reading is finished a callback will be called.
Thanks to Andrew Vovk
I scanned the Bluetooth, linked and sent instructions to start the Bluetooth device's measurement function and found the following error:
03-15 11:12:44.903 22685-22685/com.homehealth.bluetooth_one E/BluetoothGatt: android.os.DeadObjectException
at android.os.BinderProxy.transact(Native Method)
at android.bluetooth.IBluetoothGatt$Stub$Proxy.writeCharacteristic(IBluetoothGatt.java:933)
at android.bluetooth.BluetoothGatt.writeCharacteristic(BluetoothGatt.java:952)
at com.homehealth.bluetooth_one.BluetoothLeService.wirteCharacteristic(BluetoothLeService.java:283)
at
When I connect the bluetooth with my phone, I want to send CMD to bluetooth device and getting the characteristic .
I use the methods that mBluetoothGatt.writeCharacteristic(characteristic),mBluetoothGatt.readCharacteristic(characteristic),mBluetoothGatt.setCharacteristicNotification(characteristic, enabled),It is error.
myCode:
Activity :
if (uuid.contains("fff3")){
mBluetoothLeService.wirteCharacteristic(gattCharacteristic);
mBluetoothLeService.setCharacteristicNotification(gattCharacteristic, true);
mBluetoothLeService.readCharacteristic(gattCharacteristic);
}
Service class is :
public void wirteCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
boolean success = mBluetoothGatt.writeCharacteristic(characteristic);
if (success) Log.i(TAG,"wirteCharacteristic successful");
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoohAdapter not initialized");
return;
}
Log.i(TAG,"readCharacteristic UUID="+characteristic.getUuid().toString());
boolean success = mBluetoothGatt.readCharacteristic(characteristic);
if (success) Log.i(TAG,"readCharacteristic successful");
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
boolean successful = mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
mBluetoothGatt.writeCharacteristic(characteristic);
if (successful) {
Log.i(TAG,"setCharacteristicNotification successful");
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(characteristic.getUuid());
if (null == descriptor) {
Log.e(TAG, "descriptor is null,or UUID is invalid uuid=" + characteristic.getUuid());
return;
}
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
It is the problem that mBluetoothGatt.writeCharacteristic(characteristic).
characteristic is not setting Value.
the right code is :
characteristic.setValue(bytes);
mBluetoothGatt.writeCharacteristic(characteristic);
I try to read some configurations from a device I'm connected to, but on the callback - onCharacteristicRead the parameter status=10.
I noticed that status == 0 meas BluetoothGatt.GATT_SUCCESS.
WHAT DOES 10 STANDS FOR????
My code is as follows:
public boolean read(byte[] bytes, String action) {
// is copied from android website example
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return false;
}
BluetoothGattService mCC2540_service = mBluetoothGatt.getService(UUID.fromString(mCC2540_SERVICE_UUID));
if (mCC2540_service == null){
Log.e(TAG, "mCC2540_service == null");
return false;
}
BluetoothGattCharacteristic bluetoothGattCharacteristic = mCC2540_service.getCharacteristic(UUID.fromString("0000fffc-0000-1000-8000-00805f9b34fb"));
bluetoothGattCharacteristic.setValue(bytes);
if ((bluetoothGattCharacteristic.getProperties() | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
mBluetoothGatt.setCharacteristicNotification(bluetoothGattCharacteristic, true);
}
boolean status = mBluetoothGatt.readCharacteristic(bluetoothGattCharacteristic);
Log.d(TAG, "read() command sent");
return status;
}
I am working on a BLE project (Android application) using Android 4.3 API, i have used sample BLE app it is only reading characteristics in DeviceControlActivity.activity, but i want to write characteristics and send it to BLE chip on clicking a button. How can I write data on chip cc2540 .. Basically i don't know the step by step procedure to write characteristics.
write i can only see the name and id of device with following piece of code in DeviceControlActivity
private final ExpandableListView.OnChildClickListener servicesListClickListner =
new ExpandableListView.OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
if (mGattCharacteristics != null) {
final BluetoothGattCharacteristic characteristic =
mGattCharacteristics.get(groupPosition).get(childPosition);
final int charaProp = characteristic.getProperties();
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(characteristic);
showDialog("reading");
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.writeCharacteristic(characteristic);
showDialog("writing");
//characteristic.setValue(bytes);
//characteristic.setValue("testing");
//characteristic.setWriteType(BluetoothGattCharacteristic.PERMISSION_WRITE);
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
mNotifyCharacteristic = characteristic;
mBluetoothLeService.setCharacteristicNotification(
characteristic, true);
}
byte[] value = {0x00, (byte) (0xB9) , 0x0D, (byte) (0x90), 0x2F};
if(!characteristic.setValue(value))
{
Log.w(TAG, "Couldn't set characteristic's local value");
//return;
}
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
/*if(!writeCharacteristic.writeCharacteristic(characteristic))
{
Log.w(TAG, "Couldn't write characteristic");
}*/
return true;
}
return false;
}
};
The following code is write characteristic using byte[] data:
public boolean writeCharacteristic(){
//check mBluetoothGatt is available
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
BluetoothGattService Service = mBluetoothGatt.getService(your Services);
if (Service == null) {
Log.e(TAG, "service not found!");
return false;
}
BluetoothGattCharacteristic charac = Service
.getCharacteristic(your characteristic);
if (charac == null) {
Log.e(TAG, "char not found!");
return false;
}
byte[] value = new byte[1];
value[0] = (byte) (21 & 0xFF);
charac.setValue(value);
boolean status = mBluetoothGatt.writeCharacteristic(charac);
return status;
}
Please note that the logic OR in:
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0)" in the original post should be a logic AND for the permission check to work. Same for the second charaProp comparison. Otherwise bot statements are true regardless of the actual permission flag.
The following code is write characteristic using string data in utf-8 format:
public void writeCharacteristic(BluetoothGattCharacteristic characteristic,
String data) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
Log.i(TAG, "characteristic " + characteristic.toString());
try {
Log.i(TAG, "data " + URLEncoder.encode(data, "utf-8"));
characteristic.setValue(URLEncoder.encode(data, "utf-8"));
// TODO
mBluetoothGatt.writeCharacteristic(characteristic);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
Hope it helps!
public boolean writeCharacteristic(byte value[],int type){
//check mBluetoothGatt is available
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
BluetoothGattService Service = mBluetoothGatt.getService(UUID_SIMPLESERVICE);
if (Service == null) {
Log.e(TAG, "service not found!");
//////////NO service found...........
return false;
}
BluetoothGattCharacteristic charac1 = null;
boolean status1 = false;
if(type==1) {
charac1 = Service.getCharacteristic(UUID_PORT1);
charac1.setValue(value);
status1 = mBluetoothGatt.writeCharacteristic(charac1);
Log.v("________BLESERVICE____", "___WRITE CHARATERISTICS STATUS:_________"+status1);
onReliableWriteCompleted(status1);
}
if (charac1 == null) {
Log.e(TAG, "char not found!");
return false;
}
Log.v("___TYPE___","______________________"+type);
return status1;
}