5

I have two devices that I'm connecting to. When I leave the app I'm disconnecting from the devices. Both go through the same process but sometimes one of the devices maintains a connection until I force close the app.

I have indicator lights on the devices confirming that it still thinks it's connected and other instances of the app cannot connect to it until I force close the first. In the log below the first listed device stayed connected.

//call gatt.disconnect();
BluetoothGatt: cancelOpen() - device: F0:3D:A0:04:CA:E7
BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=F0:3D:A0:04:CA:E7

//wait for connection state change callback then call gatt.close();
BluetoothGatt: close()
BluetoothGatt: unregisterApp() - mClientIf=7

//call gatt.disconnect();
BluetoothGatt: cancelOpen() - device: FF:A9:CA:EF:08:A4
BluetoothGatt: onClientConnectionState() - status=0 clientIf=5 device=FF:A9:CA:EF:08:A4

//wait for connection state change callback then call gatt.close();
BluetoothGatt: close()
BluetoothGatt: unregisterApp() - mClientIf=5

After I call gatt.close() I grab the BluetoothManager and look for my device in the list of connected devices. It's in the list.

From BluetoothGattCallback

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
    super.onConnectionStateChange(gatt, status, newState);
    final String address = gatt.getDevice().getAddress();
    if (newState == BluetoothProfile.STATE_CONNECTED) {
        onConnected(gatt, address);
    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
        onDisconnected(gatt, address);
    }
}

private void onDisconnected(BluetoothGatt gatt, String address) {
    Log.v(TAG, address + " disconnected");
    if (devices.containsKey(address)) {
        devices.get(address).setState(Connection.STATE_DISCONNECTED);
        connect(gatt.getDevice());
    } else {
        gatt.close();
        verifyDisconnect(gatt, address);
    }
}

private void verifyDisconnect(BluetoothGatt gatt, String address) {
    BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
    final List<BluetoothDevice> devices = bluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
    for (final BluetoothDevice device : devices) {
        if (device.getAddress().equals(address)) {
            Log.d(TAG, address + " is still connected!!!!");
            addCommand(new DisconnectCommand(gatt));
            break;
        }
    }
}

This class is added to a command queue.

public class DisconnectCommand extends BluetoothCommand {

    private final BluetoothGatt gatt;

    public DisconnectCommand(BluetoothGatt gatt) {
        this.gatt = gatt;
        priority = BluetoothCommand.DISCONNECT_PRIORITY;
    }

    public boolean execute() {
        gatt.disconnect();
        return true;
    }
}
Jeff Engebretsen
  • 666
  • 2
  • 8
  • 21
  • The reason you are seeing the device in the list despite closing the GATT db, is Android's Bluetooth stack, has cached it. See [this](http://stackoverflow.com/questions/22596951/how-to-programmatically-force-bluetooth-low-energy-service-discovery-on-android) that might give you a clue. – t0mm13b Oct 20 '15 at 22:42
  • It only shows up in the list when the device's indicator lite is also on. That solution applies to discovering services not disconnecting. – Jeff Engebretsen Oct 20 '15 at 22:50
  • Did you call the `disconnect()` method of the BluetoothGatt prior to calling `close()`? – t0mm13b Oct 20 '15 at 22:58
  • Yes. I marked where I called the two methods in the log above. – Jeff Engebretsen Oct 20 '15 at 23:02
  • It would help to post some code to see where is it going wrong, looking at the above logs is not exactly helpful. – t0mm13b Oct 20 '15 at 23:04
  • Having same issue, friends. Anyone find a solution? – ALamp May 07 '18 at 20:27

2 Answers2

1

You have to call first

bluetoothGatt.disconnect();

Then you have to wait for the callback to be called so that you can close the connection successfully

public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                                int newState) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    Log.d(TAG, "Connected to GATT server.");
                    bluetoothGatt.discoverServices(); // onServicesDiscovered callback will handle the action
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    bluetoothGatt.close();
                    bluetoothGatt = null;
                    Log.d(TAG, "Disonnected fromActivity GATT server.");
                }
            }
0

try:

public void disconnect() {
    if (blegatt== null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
    }
    else {
        bleGatt.disconnect();
        close();
        gatt = null;
    }
}
/**
 * After using a given BLE device, the app must call this method to ensure resources are
 * released properly.
 */
public void close() {
    if (gatt == null) {
        return;
    }
    gatt.close();
}