mBluetoothGatt.getService(uuid) returns null - android

In my app , i am passng the UUID number of the hearing aid service as in the BLE sample from google i.e. 0000a00-0000-1000-8000-00805f9b34fb
But the getservice returns null means that the service is not supported by the BluetoothGatt .
Why is this happening , can anybody please help me .

You have to first discover all services for the given device per documentation.
This function requires that service discovery has been completed for the given device.
http://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#getService(java.util.UUID)
#Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService mBluetoothGattService = mBluetoothGatt.getService(UUID.fromString(serviceUUID));
if (mBluetoothGattService != null) {
Log.i(TAG, "Service characteristic UUID found: " + mBluetoothGattService.getUuid().toString());
} else {
Log.i(TAG, "Service characteristic not found for UUID: " + serviceUUID);
}
}
Or you can just run a search
for (BluetoothGattService gattService : gattServices) {
Log.i(TAG, "Service UUID Found: " + gattService.getUuid().toString());
}

Try doing a full discover[1] of the remote database and then iterate through the services. Maybe you've got the UUID wrong.
[1] http://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#discoverServices()

Your UUID is also wrong. It should be 0000a00X-0000-1000-8000-00805f9b34fb, not 0000a00-0000-1000-8000-00805f9b34fb

Related

BluetoothGattCharacteristic.value returns empty value

I am trying to parse a value of a BluetoothGattCharacteristic to another activity. I can read the characteristic successfully, but then the value it gives me is empty...
I am trying to read the device name. In another BLE app (nRF connect) can I see the characteristic and its value. Can someone help me, what am I doing wrong?
This method loops and logs the services found with its characteristics:
private void displayGattServices(List<BluetoothGattService> gattServices) {
//Check if there is any gatt services. If not, return.
if (gattServices == null) return;
// Loop through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
Log.i(TAG, "SERVICE FOUND: " + gattService.getUuid().toString());
//Loop through available characteristics for each service
for (BluetoothGattCharacteristic gattCharacteristic : gattService.getCharacteristics()) {
Log.i(TAG, " CHAR. FOUND: " + gattCharacteristic.getUuid().toString());
}
}
//****************************************
// CONNECTION PROCESS FINISHED!
//****************************************
Log.i(TAG, "*************************************");
Log.i(TAG, "CONNECTION COMPLETED SUCCESFULLY");
Log.i(TAG, "*************************************");
goToDisplayBleServicesActivityOnListItemClick();
}
goToDisplayBleServiceActivityOnListItemClick():
private void goToDisplayBleServicesActivityOnListItemClick() {
Intent intent = new Intent(this, displayBleServicesActivity.class);
BluetoothGattService selectedService = mBluetoothGatt.getService(UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"));
BluetoothGattCharacteristic selectedCharacteristic = selectedService.getCharacteristic(UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb"));
if (mBluetoothGatt.readCharacteristic(selectedCharacteristic)) {
intent.putExtra("READ_CHAR", selectedCharacteristic.getValue().toString());
} else {
intent.putExtra("READ_CHAR", "It did not work out");
}
startActivity(intent);
}
What am I doing wrong here?
If you read the documentation at https://developer.android.com/reference/android/bluetooth/BluetoothGatt#readCharacteristic(android.bluetooth.BluetoothGattCharacteristic) it says:
This is an asynchronous operation. The result of the read operation is reported by the BluetoothGattCallback#onCharacteristicRead callback.
So you must override the onCharacteristicRead callback. Inside that one you can get the value.

BLE Gatt onConnectionStateChanged failed with status 257 in Android

I am developping a Android app that connects to multiple BLE devices at the same time, after that i read characteristic permanently from those devices but after a while, I am getting a status 257 in the onConnectionStateChanged() function, the android documentation doesn't explain what is the reason of the error, or how to fix it.
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i("TAG","onConnectionStateChange, status : "+status+" parseConnection : "+ GattStatusParse.parseConnection(status)+" or "+ GattStatusParse.parseConnection(status));
isConnected = BluetoothProfile.STATE_CONNECTED == newState;
if (status == BluetoothGatt.GATT_SUCCESS) {
if (isConnected) {
Log.i(TAG, "GATT connected." + connectedBluethoothDevice.toString());
gatt.discoverServices();
} else {
Log.i("TAG"," GATT disconnected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.remove(device);
}
}else{
if (connectedBluethoothDevice.contains(device)) {
int mConnectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);
if(mConnectionState==BluetoothProfile.STATE_DISCONNECTED || mConnectionState==BluetoothProfile.STATE_DISCONNECTING){
connectedBluethoothDevice.remove(device);
}
}
}
}
could anyone help me to fix this problem, thanks.
I also didn't find error code 257 in the documentation, but my observation is that this code means that you are trying to connect to a Bluetooth device too many times in too short time. Reconnecting bluetooth on your phone should resolve this issue.

Get secondary bluetooth gatt service android

Fetch android secondary bluetooth gatt service from bluetooth android API's.
Currently below is the code where we fetch ble services :
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
List<BluetoothGattService> gattServices = mBluetoothGatt.getServices();
Log.e("onServicesDiscovered", "Services count: "+gattServices.size());
BluetoothGattService bleServ = mBluetoothGatt.getService(UUID.fromString("22222222-0000-0000-0000-000000000000"));
for (BluetoothGattService gattService : gattServices) {
String serviceUUID = gattService.getUuid().toString();
Log.e("onServicesDiscovered", "Service uuid "+serviceUUID);
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
Even tried fetching exclusively the secondary service but it returns null object :
BluetoothGattService bleServ = mBluetoothGatt.getService(UUID.fromString("22222222-0000-0000-0000-000000000000"));
Can someone point any pointers how to search secondary ble service in Android.
You should use this method: https://developer.android.com/reference/android/bluetooth/BluetoothGattService.html#getIncludedServices() on a primary service.

Receiving multiple BLE Packets per one connection interval in Android

My device information
Nordic board :
MTU size : 247.
This board send notification multiple packets in one connection interval (Just counter value like 1,2,3,4...) at "Heart Rate Measurement".
Android device :
Version 5.0 and 6.0. (Using two device).
communicate Bluetooth Low Energy(BLE) with board.
board connect with my Android app MTU is setting 244.
Application source is google sample project BluetoothLeGatt
App send notification value at "Heart Rate Service" characteristic.
Receive notification value at Gattcallback "onCharacteristicChanged()"
Problem
My Android app lost some packet.
I read this post. Maximizing BLE Throughput on iOS and Android. So I send E-mail this post author and I search another information for Android.
I found some similarly question. but that question answer was not work. Then I found one question what I want exactly. but this question have no answers. Android receiving multiple BLE packets per connection interval. Unfortunately I don't have any reply E-mail answer.
My question is how do I set Android BLE notification. (Not Nordic board setting)
(My question is same Android receiving multiple BLE packets per connection interval)
Under line is my sample code. at notification.
#Connect
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;
}
}
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;
}
#GattCallback
/*broadcastUpdate method is display value*/
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:");
mBluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
mConnectionState = STATE_DISCONNECTED;
broadcastUpdate(ACTION_GATT_DISCONNECTED);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "onServicesDiscovered success: (status)" + status);
//findServiceOther(gatt);
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
Log.d(TAG, "Request MTU");
gatt.requestMtu(SET_MTU);
} else {
Log.w(TAG, "onServicesDiscovered failed: (status)" + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "onCharRead Success");
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
} else {
Log.d(TAG, "OnCharRead Error: " + status);
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if (characteristic.getUuid().equals(SampleGattAttributes.UUID_HEART_RATE_MEASUREMENT))
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic, FLAG_HEART_RATE);
else
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
#Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
boolean priority = gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
Log.d(TAG, "MTU changed (mtu/status) / Priority : (" + mtu + "/" + status + ") / " + priority);
changed_MTU_Size = mtu;
broadcastUpdate(ACTION_DATA_AVAILABLE, changed_MTU_Size, FLAG_MTU);
broadcastUpdate(ACTION_GATT_CONNECTED);
}
#set notification
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if (SampleGattAttributes.UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
// This is specific to Heart Rate Measurement.
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(SampleGattAttributes.UUID_CLIENT_CHARACTERISTIC_CONFIG);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
Edit_1
I test Nordic offical app in Google play store.
nRF Connect for Mobile
but this app miss packet too.
Edit_2
I found some problem too.
< Nordic board constant setting>
HEART_RATE_MEAS_INTERVAL : 10
MIN_CONN_INTERVAL : MSEC_TO_UNITS(40, UNIT_1_25_MS)
MAX_CONN_INTERVAL : MSEC_TO_UNITS(40, UNIT_1_25_MS)
SLAVE_LATENCY 0
CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)
< Run in my Android app >
skip requestMTU : receive 20byte packet successful. (Data rate average is 2200byte/second in my app)
requestMTU : I try so many MTU size (ex: 23(can small size), 40, 100, 255(target) ...) but lost some packet (Data rate 8500 ~ 9500 byte/second in my app)
I wonder requestMTU and notification receive interrelation.
i have implemented a file transfer over LE on a nrf51422 and SD310 by using the Nordic UART Service. The android App is written in CPP by using Qt and the QtBluetooth library. Therefore, this answer my not really help you. But, i have taken some afford to achive a usable data rate. 1st, set the connection parameters to 7.5ms (min) and 15ms (max). 2nd, on the peripheral side, i send up to 7 packets (til the buffer is full). So the peripheral send up to 7 packets per connection event.
On the Android side, the charachteritic changed event arrive me frequently with a data size of 20 bytes (due to the maximum MTU size of 23, 3 bytes used by nordic uart service) and i read the data instantly.
Perhaps your mistake is the MTU size of 244. The default BLE MTU size is 23 (Core spec 4.1).
Regards

Android BLE readCharacteristic fails

I'm trying to read the initial state of a BLE device when I connect to it. Here's the code I have to try to do that:
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status)
{
if(status == BluetoothGatt.GATT_SUCCESS)
{
Log.i(TAG, gatt.getDevice().toString() + "Discovered Service Status: " + gattStatusToString(status));
for(BluetoothGattService service : gatt.getServices())
{
Log.i(TAG, "Discovered Service: " + service.getUuid().toString() + " with " + "characteristics:");
for(BluetoothGattCharacteristic characteristic : service.getCharacteristics())
{
// Set notifiable
if(!gatt.setCharacteristicNotification(characteristic, true))
{
Log.e(TAG, "Failed to set notification for: " + characteristic.toString());
}
// Enable notification descriptor
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CCC_UUID);
if(descriptor != null)
{
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
// Read characteristic
if(!gatt.readCharacteristic(characteristic))
{
Log.e(TAG, "Failed to read characteristic: " + characteristic.toString());
}
}
}
}
else
{
Log.d(TAG, "Discover Services status: " + gattStatusToString(status));
}
}
But the read fails every time! Later if I initiate a read based on UI interaction it reads just fine! Any ideas about what's going on here?
In the Android BLE implementation, the gatt operation calls need to be queued so that only one operation (read, write, etc.) is in effect at a time. So for example, after gatt.readCharacteristic(characteristicX) is called, you need to wait for the gatt callbackBluetoothGattCallback.onCharacteristicRead() to indicate the read is finished. If you initiate a second gatt.readCharacteristic() operation before the previous one completes, the second one will fail (by returning false) This goes for all of the gatt.XXX() operations.
Its a little work, but I think the best solution is to create a command queue for all the gatt operations and run them one at a time. You can use the command pattern to accomplish this.

Categories

Resources