3

I am in the process of writing an Android application that will connect to a health device over Bluetooth LE. However, it seems as though I am not connecting to its GATT server properly. Every few seconds, my log file shows this:

03-27 11:33:39.821: D/BluetoothAdapter(26644): onScanResult() - Device=0C:F3:EE:AA:33:35 RSSI=-53
03-27 11:33:39.821: I/BluetoothGattActivity(26644): New LE Device: BT-001 @ -53
03-27 11:33:39.821: I/BluetoothGattActivity(26644): New LE Device matches !!!
03-27 11:33:39.831: I/BluetoothGattActivity(26644): In the fish function.
03-27 11:33:39.831: D/BluetoothGatt(26644): connect() - device: 0C:F3:EE:AA:33:35, auto:  false
03-27 11:33:39.831: D/BluetoothGatt(26644): registerApp()
03-27 11:33:39.831: D/BluetoothGatt(26644): registerApp() - UUID=7155a6e0-5432-42cc-8b05-a080c86aaccb
03-27 11:33:39.841: I/BluetoothGatt(26644): Client registered, waiting for callback
03-27 11:33:49.840: E/BluetoothGatt(26644): Failed to register callback
03-27 11:33:49.840: I/BluetoothGattActivity(26644): myBluetoothGatt is null

If someone could help me see where my issue is and what's going on, it would be greatly appreciated. I am using a Galaxy s4. I believe all my relevant code is below:

private void broadcastUpdate(final String action) {
   final Intent intent = new Intent(action);
   sendBroadcast(intent);
}

private void fish(final BluetoothDevice device) {      
   Log.i(TAG, "In the fish function.");
   myBluetoothGatt = device.connectGatt(this, false, myGattCallback);
   Log.i(TAG, "myBluetoothGatt is " + myBluetoothGatt);
}

private BluetoothAdapter.LeScanCallback callbackFunction = new BluetoothAdapter.LeScanCallback() {
   @Override
   public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
       Log.i(TAG, "New LE Device: " + device.getName() + " @ " + rssi);
       if (DEVICE_NAME.equals(device.getName())) {
           Log.i(TAG, "New LE Device matches !!!");
           fish (device);
           }
   }
};

private final BluetoothGattCallback myGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        String intentAction;
        Log.i(TAG, "We are in the ConnectionStateChanged().");
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            intentAction = ACTION_GATT_CONNECTED;
            mConnectionState = STATE_CONNECTED;
            broadcastUpdate(intentAction);
            Log.i(TAG, "Connected to GATT server.");
            Log.i(TAG, "Attempting to start service discovery:" +
                    myBluetoothGatt.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) {
        Log.i(TAG, "In area 1");
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            System.out.println("--onServicesDiscovered");
        } else {
            Log.w(TAG, "onServicesDiscovered received: " + status);
        }
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {
        Log.i(TAG, "In area 2");
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_DATA_AVAILABLE);
            Log.i(TAG, "--onCharacteristicRead GATT_SUCCESS");
        }
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic) {
        Log.i(TAG, "In area 3");
        broadcastUpdate(ACTION_DATA_AVAILABLE);
        System.out.println("--onCharacteristicChanged");
    }
};
jgriner91
  • 51
  • 1
  • 5

3 Answers3

4

The call to device.connectGatt(this, false, myGattCallback), should be done on main UIThread. So it should be something like this:

private void fish(final BluetoothDevice device) {
        Log.i(TAG, "In the fish function.");
        runOnUiThread(new Runnable() {
          @Override
          public void run() {
              myBluetoothGatt = device.connectGatt(this, false, myGattCallback);
          }
        });
}
Álvaro Pérez Soria
  • 1,443
  • 1
  • 13
  • 26
2

I have a partial fix for this particular form of the error. I saw in this question GATT callback fails to register that Samsung devices require Gatt discovery attempts to be done on the UI thread.

The tricky part for me was realizing that I wasn't on the thread I thought I was. The onLeScan callback was not returning on the UI thread, but instead on a Binder thread (at least according to the debugger). I wound up having to use a Handler to post a Runnable which kicked off my service discovery code.

The reason this is a partial fix is that now I'm in a state where the Gatt connection isn't null but Hangs after these lines

04-04 14:21:15.115    9616-9616/BluetoothApp I/BluetoothGatt﹕ Client registered, waiting for callback
04-04 14:21:15.115    9616-9627/BluetoothApp D/BluetoothGatt﹕ onClientRegistered() - status=0 clientIf=5

I haven't yet figured out how to solve this last issue, but this should get you one step further.

Community
  • 1
  • 1
Travis Castillo
  • 1,807
  • 1
  • 20
  • 23
0

Register both callback and device.connectGatt(this, false, myGattCallback) inside a bind service and for further communication use broadcast receiver.

Once you receive event or data in call back just broad cast the same and receive it from reciver (Which should be written in app as a separate or inside main activity if you use only one activity and rest of all are fragments ).

Gopal Sharma
  • 300
  • 4
  • 14