Huy Tower
Huy Tower

Reputation: 7966

Can not discover Service and Characteristics via Bluetooth Low Energy - BLE

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

Answers (4)

Michael
Michael

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

FishingIsLife
FishingIsLife

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

Developer
Developer

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

Chris
Chris

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

Related Questions