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");
}
};
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);
}
});
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With