ongebear
ongebear

Reputation: 35

Proper method for discovering BLE services

I keep getting the error:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.UUID android.bluetooth.BluetoothGattService.getUuid()' on a null object reference

when trying to 'get' a known service and characteristic using UUIDs. The documentation says that I need to discover services first, but I guess I'm doing that incorrectly? Here is my connect method:

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void Connect(View view){

    Device=Adapter.getRemoteDevice("3C:A3:08:94:C3:11");

    Gatt=Device.connectGatt(this,true,GattCallback);

    Gatt.discoverServices();

    Service=Gatt.getService(UUID.fromString("0000FFE0-0000-1000-8000-00805F9B34FB"));

    ErrorID.setText(Service.getUuid().toString());

    Characteristic=Service.getCharacteristic(UUID.fromString("0000FFE1-0000-1000-8000-00805F9B34FB"));

    threadStatus=true;

    //connected indicator

}

The textView is there to confirm that the service has been located. I've tried adding delays after discoverServices() but that didn't work. Using onServicesDiscovered() afterwards also didn't work. I'm new to Java and Android sorry if my question is silly, thank you!

Upvotes: 0

Views: 1195

Answers (2)

Sam
Sam

Reputation: 3155

You need to have the GattCallback in which you override the callback methods. you need to define your GattCallback something like code below. And when you receive a callback, perform the appropriate action.

private final BluetoothGattCallback GattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                // This is where you call to discover services. 
                Gatt.discoverServices();

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                // This is where you will call the method to get the service
                Service=Gatt.getService(UUID.fromString("0000FFE0-0000-1000-8000-00805F9B34FB"));
            } else {
            }
        }

    };

Upvotes: 1

stkent
stkent

Reputation: 20128

After calling

Gatt=Device.connectGatt(this,true,GattCallback);

you must wait for the onConnectionStateChange method of your GattCallback to be called (with an appropriate status) before doing anything else.

Once that happens, you'll need to call discoverServices on your Gatt instance, and wait once more for the onServicesDiscovered method of your GattCallback to be called.

Only at this point, after onServicesDiscovered has been called, can you call Gatt.getService and expect to receive a non-null result. This is true even if you know what services you expect to exist on the device.

Upvotes: 0

Related Questions