Reputation: 7966
I am working on Bluetooth Low Energy - BLE.
I can scan and find out, connect to firmware devices via Bluetooth by using BLE.
mBluetoothGatt = mAl.get(pos).connectGatt(mContext, false, mGattCallback);
While app from Play store can discover Services
and Characteristics
inside firmware device, my android application can not discover them, it always return empty services list. Actually Firmware device already set up Services
and Characteristics
also.
I don't know why, who know why, please help me how to discover Services
and Characteristics
,
Thank you,
Java code
// Various callback methods defined by the BLE API.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
/**
* In case already connected to Pas device
*/
Log.i("", "Connected to GATT server. " + gatt.discoverServices());
// CALL THIS METHOD TO BEGIN DISCOVER SERVICES
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
/**
* In case disconnected Pas device
*/
Log.i("", "Disconnected from GATT server.");
}
}
@Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.i("", "onServicesDiscovered " + status + " " + gatt.discoverServices()
+ " " + gatt.getServices());
// RETURN : []
Log.i("", "gatt.getServices() " + gatt.getServices());
// RETURN : TRUE
Log.i("", "gatt.getServices() " + gatt.getServices().isEmpty());
// EXCEPTION HAPPEN BCS SIZE = 0
gatt.readCharacteristic(gatt.getServices().get(0).getCharacteristics().get(0));
if (status == BluetoothGatt.GATT_SUCCESS) {
} else {
Log.w("", "onServicesDiscovered received: " + status);
}
}
@Override
// Result of a characteristic read operation
public void onCharacteristicRead(
BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status) {
Log.i("", "onCharacteristicRead " + status + " " + characteristic);
if (status == BluetoothGatt.GATT_SUCCESS) {
}
}
};
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
/**
* Should show Scan Pas Devices :
* Add to array list scanned pas devices if it is not exist in list
* before
*/
if (!mAlPasDeviceNames.contains(device.getName())) {
mAlPasDevices.add(device);
mAlPasDeviceNames.add(device.getName());
// set adapter and show on UI
mLv.setAdapter(new PasConnectionAdapter(
getActivity(),
R.layout.simple_list_item_scan_pas_device,
mAlPasDevices));
}
}
});
}
};
Logcat
connect() - device: E2:5A:6B:5A:18:57, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=93455863-c385-4563-9197-6592024cc8cc
D/BtGatt.GattService: registerClient() - UUID=93455863-c385-4563-9197-6592024cc8cc
D/BtGatt.GattService: onClientRegistered() - UUID=93455863-c385-4563-9197-6592024cc8cc, clientIf=5
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=5
D/BtGatt.GattService: clientConnect() - address=E2:5A:6B:5A:18:57, isDirect=true
E/BluetoothRemoteDevices: aclStateChangeCallback: Device is NULL
D/BtGatt.GattService: onConnected() - clientIf=5, connId=5, address=E2:5A:6B:5A:18:57
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=5 device=E2:5A:6B:5A:18:57
D/BluetoothGatt: discoverServices() - device: E2:5A:6B:5A:18:57
D/BtGatt.GattService: discoverServices() - address=E2:5A:6B:5A:18:57, connId=5
I/: Connected to GATT server. true
D/BluetoothGatt: discoverServices() - device: E2:5A:6B:5A:18:57
D/BtGatt.GattService: discoverServices() - address=E2:5A:6B:5A:18:57, connId=5
D/BtGatt.GattService: onSearchCompleted() - connId=5, status=0
D/BtGatt.GattService: onSearchCompleted() - connId=5, status=0
E/BtGatt.btif: bta_to_btif_uuid: Unknown UUID length 61618!
E/BtGatt.btif: bta_to_btif_uuid: Unknown UUID length 61619!
I/: gatt.getService(uuid) null
D/BluetoothGatt: onSearchComplete() = Device=E2:5A:6B:5A:18:57 Status=0
D/BluetoothGatt: discoverServices() - device: E2:5A:6B:5A:18:57
D/BtGatt.GattService: discoverServices() - address=E2:5A:6B:5A:18:57, connId=5
D/BtGatt.GattService: onSearchCompleted() - connId=5, status=0
I/: onServicesDiscovered 0 true []
I/: gatt.getServices() []
I/: gatt.getServices() true
E/BtGatt.btif: bta_to_btif_uuid: Unknown UUID length 61621!
W/BluetoothGatt: Unhandled exception in callback
W/BluetoothGatt: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
W/BluetoothGatt: at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
W/BluetoothGatt: at java.util.ArrayList.get(ArrayList.java:308)
W/BluetoothGatt: at ui.fragment.PasConnectionFragment$1.onServicesDiscovered(PasConnectionFragment.java:379)
W/BluetoothGatt: at android.bluetooth.BluetoothGatt$1.onSearchComplete(BluetoothGatt.java:304)
W/BluetoothGatt: at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:217)
W/BluetoothGatt: at android.os.Binder.execTransact(Binder.java:446)
Upvotes: 2
Views: 14062
Reputation: 39
I faced the same issue. I called discoverServices()
, but nothing happened. Then I found the solution. You must call discoverServices()
only after you have successfully connected to the device. Here is my code:
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if(newState == BluetoothProfile.STATE_CONNECTED) {
Log.d(TAG, "Connected to GATT server, discovering services...");
gatt.discoverServices();
} else if(newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d(TAG, "Disconnected from GATT server");
}
}
Here I try to discover the services only after connecting to the device. This worked for me and I was able to retrieve the desired service ids in the onServicesDiscovered()
method.
Hope I helped...
Upvotes: 0
Reputation: 2362
You can display the provided services and Characteristics as follows:
for (BluetoothGattService service : gatt.getServices()) {
Log.d(TAG, "Found Service " + service.getUuid().toString());
for(BluetoothGattCharacteristic mcharacteristic :service.getCharacteristics())
{
Log.d(TAG, "Found Characteristic " + mcharacteristic.getUuid().toString());
}
}
But maybe this won't work or it will show you only the generic attribute profile o.e. Then it seems that the manufacturer exchanged Data before making the rest of the services and Characteristics visible. In this case if you use an android phone you can use hci log and inspect it in wireshark. There you can sniff the exchanged packages. it's not easy and depends ob complexity to "hack" the profile but without documentation it's the only thing you might be able to to.
Upvotes: 0
Reputation: 101
Check the following code it will show you number of servieces and its uuids
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.e("BluetoothLeService", "onServicesDiscovered()");
if (status == BluetoothGatt.GATT_SUCCESS) {
List<BluetoothGattService> gattServices = mBluetoothGatt.getServices();
Log.e("onServicesDiscovered", "Services count: "+gattServices.size());
for (BluetoothGattService gattService : gattServices) {
String serviceUUID = gattService.getUuid().toString();
Log.e("onServicesDiscovered", "Service uuid "+serviceUUID);
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
Upvotes: 3
Reputation: 4386
One issue is probably that you call gatt.discoverServices() several times. Two times in the onConnectionStateChange method:
Log.i("", "Connected to GATT server. " + gatt.discoverServices());
// CALL THIS METHOD TO BEGIN DISCOVER SERVICES
gatt.discoverServices();
and then again in the onServicesDiscovered method.
Log.i("", "onServicesDiscovered " + status + " " + gatt.discoverServices()
+ " " + gatt.getServices());
That means you start the service scan over and over again. Don't call it in the Log, one time is enough.
Upvotes: 3