Obsolete
Status Update
Comments
em...@gmail.com <em...@gmail.com> #2
I can confirm this on Android 4.4.4 with Cyanogen Oneplus.
em...@gmail.com <em...@gmail.com> #3
Still present in Android Lollipop 5.0.1 on Nexus 5 and Nexus 6. Is anyone at Google actually reading the bug reports? This one is quite old and should be very easy to fix...
en...@google.com <en...@google.com>
em...@gmail.com <em...@gmail.com> #5
In what way is this obsolete?
As you can see, this is still present in the master branch athttps://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothGatt.java .
Why not just fix it by moving "mAutoConnect = autoConnect;" above "if (!registerApp(callback)) {"?
As you can see, this is still present in the master branch at
Why not just fix it by moving "mAutoConnect = autoConnect;" above "if (!registerApp(callback)) {"?
la...@gmail.com <la...@gmail.com> #6
I just got 5.1.1 update on Samsung Galaxy S6 and it triggered the same error. Cant connect to BLE devices, always getting GATT 133 error.
na...@gmail.com <na...@gmail.com> #7
Same problem here, cannot send data to BLE device, return status code 133. However my app works fine on android 4.3.
ju...@gmail.com <ju...@gmail.com> #8
If you get status 133 from onConnectionStateChange() it means that the connection attempt timed out. This happens to direct connections (autoConnect = false) after 10 seconds if I recall correctly.
na...@gmail.com <na...@gmail.com> #9
Thanks for your comment, I'm actually get a 133 error/status code on "onCharacteristicWrite()", connection to the BLE device does not have any problem. Regards, J.
so...@gmail.com <so...@gmail.com> #10
On S6 the old api's does not workm try with new scan api's
ro...@gmail.com <ro...@gmail.com> #11
I can confirm this issue with the Galaxy S6 and Android 5.1. Any workaround?
[Deleted User] <[Deleted User]> #12
You can use https://github.com/Polidea/RxAndroidBle library which has implemented a workaround for this issue. Dealing with bluetooth on Android is really painful and this library solves many problems - it has a dedicated blocking queue for all ble operations and runs them on ui thread.
If you are curious, you can find the implementation of the workaround here:
https://github.com/Polidea/RxAndroidBle/blob/master/rxandroidble/src/main/java/com/polidea/rxandroidble/internal/util/BleConnectionCompat.java
If you are curious, you can find the implementation of the workaround here:
i4...@gmail.com <i4...@gmail.com> #13
[Comment deleted]
i4...@gmail.com <i4...@gmail.com> #14
@polidea Your library doesn't seem to solve the dreaded status=133, I tried your sample app (using com.polidea.rxandroidble:rxandroidble:1.0.1) from the project. Tried to connect disconnect several times in a row and after some tries ( 4-6 tries ) it started to give me status = 133.
But, Kudos to your simple apis. Thanks
But, Kudos to your simple apis. Thanks
ro...@gmail.com <ro...@gmail.com> #15
I'm not the author of the library but i think there's not much that can be done about the dreaded status 133. At the most, close the current gatt and try to reconnect.
em...@gmail.com <em...@gmail.com> #17
[Comment deleted]
[Deleted User] <[Deleted User]> #18
Stupid question maybe, but this fix will be backwards compatible i hope?
[Deleted User] <[Deleted User]> #19
What is needed to be done to add this fix to our applications?
em...@gmail.com <em...@gmail.com> #20
There is a similar race condition as well.
If you call device.connectGatt(...) and shortly after call gatt.disconnect() to abort the connection attempt, the connection attempt will NOT be aborted.
The root cause is that after device.connectGatt(...) is called there will soon be an onClientRegistered callback which will set mClientIf to some nonzero value. But the disconnect method returns directly if mClientIf is 0, which happens if the callback has not arrived yet.
If you call device.connectGatt(...) and shortly after call gatt.disconnect() to abort the connection attempt, the connection attempt will NOT be aborted.
The root cause is that after device.connectGatt(...) is called there will soon be an onClientRegistered callback which will set mClientIf to some nonzero value. But the disconnect method returns directly if mClientIf is 0, which happens if the callback has not arrived yet.
ha...@gmail.com <ha...@gmail.com> #21
Same problem on Nexus 6P running Nougat.
Also GATT_MAX_PHY_CHANNEL seems to be still set at 6 (max clientIf = 6), which is less than half the connections that BLE chips typically support (leading to status 133 error as connections are exhauasted).
Also GATT_MAX_PHY_CHANNEL seems to be still set at 6 (max clientIf = 6), which is less than half the connections that BLE chips typically support (leading to status 133 error as connections are exhauasted).
ro...@gmail.com <ro...@gmail.com> #22
Any update or workaround on this issue? Still experiencing it
em...@gmail.com <em...@gmail.com> #23
It has been fixed in the latest Android. Which device/Android version do you experience it on? On older devices you need to use reflection to workaround the issue.
ju...@gmail.com <ju...@gmail.com> #24
The workaround is explained in my original message.
Let me give further context:
With BLE there are two ways to create a connection, either directly to the device using the "LE Create Connection" command or by adding the device or devices to a whitelist and requesting a connection to the whitelist.
Android's BLE stack, at least at the time I found this bug, used the former method when autoConnect=false (they call this "direct") and the latter when autoConnect=true (they call this "background").
A "direct" connection will time out in short order with 133 if it does not complete, mitigation of that is to call the connect() on the BluetoothGatt after the failure, this causes a background connection which either does not time out or has a much longer timeout.
Now, another difference between direct and background connection is that the direct connection attempt is more "aggressive" (scan window is larger) than the background connection. This may lead the background connection to take longer to complete.
The scan window size varies by device, at the time I found this bug it was 50% for a direct connection and 0.9% for a background connection on one device, but 50% and 50% on another so YMMV.
TL;DR;
Always call BluetoothDevice#connectGatt() with autoConnect=false (the race condition does not affect that case). If that connection times out you will get a callback with status=133. Then call BluetoothGatt#connect() to initiate a background connection.
Optionally if you want a direct connection, close() and get rid of the BluetoothGatt and create a new one with autoConnect=false.
Let me give further context:
With BLE there are two ways to create a connection, either directly to the device using the "LE Create Connection" command or by adding the device or devices to a whitelist and requesting a connection to the whitelist.
Android's BLE stack, at least at the time I found this bug, used the former method when autoConnect=false (they call this "direct") and the latter when autoConnect=true (they call this "background").
A "direct" connection will time out in short order with 133 if it does not complete, mitigation of that is to call the connect() on the BluetoothGatt after the failure, this causes a background connection which either does not time out or has a much longer timeout.
Now, another difference between direct and background connection is that the direct connection attempt is more "aggressive" (scan window is larger) than the background connection. This may lead the background connection to take longer to complete.
The scan window size varies by device, at the time I found this bug it was 50% for a direct connection and 0.9% for a background connection on one device, but 50% and 50% on another so YMMV.
TL;DR;
Always call BluetoothDevice#connectGatt() with autoConnect=false (the race condition does not affect that case). If that connection times out you will get a callback with status=133. Then call BluetoothGatt#connect() to initiate a background connection.
Optionally if you want a direct connection, close() and get rid of the BluetoothGatt and create a new one with autoConnect=false.
[Deleted User] <[Deleted User]> #25
#23 What do you mean by ~"use reflection to workaround the issue"? Can you provide a code sample.
[Deleted User] <[Deleted User]> #26
Hello All,
I am using below method to connect the BLE device with android mobile bluetooth.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
But this is only worked for first time connect
If I take out the ble device away beyond the range then come in range again then it is not reconnect the ble device autometically.
Can any one know how to auto reconnect the ble device when come in range.
I am using "ITUS key" ble device to work on.
Thanks.
I am using below method to connect the BLE device with android mobile bluetooth.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
But this is only worked for first time connect
If I take out the ble device away beyond the range then come in range again then it is not reconnect the ble device autometically.
Can any one know how to auto reconnect the ble device when come in range.
I am using "ITUS key" ble device to work on.
Thanks.
na...@gmail.com <na...@gmail.com> #27
I have met this condition before, it looks like the android device has "forgot" the bonding information it holds, hence the second time connection fails. Try to remove old bonding then bond again see if it works.
[Deleted User] <[Deleted User]> #28
Hello,
I have used below mGattCallBack method and when device is DISCONNECTED, i unpaired it.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
switch (newState) {
case BluetoothProfile.STATE_CONNECTED: {
Preferences.AppLog("Connected to GATT server.");
intentAction = ACTION_GATT_CONNECTED;
broadcastUpdate(intentAction);
mBluetoothGatt.discoverServices();
break;
}
case BluetoothProfile.STATE_DISCONNECTED: {
Preferences.AppLog("Disconnected from GATT server.");
intentAction = ACTION_GATT_DISCONNECTED;
broadcastUpdate(intentAction);
if (gatt.getDevice() != null) {
unpairDevice(gatt.getDevice());
}
break;
}
}
}
}
public static void unpairDevice(BluetoothDevice device) {
try {
Method m = device.getClass().getMethod("removeBond", (Class[]) null);
m.invoke(device, (Object[]) null);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
But still it is not auto reconnect when I bring the device in range.
I have used below mGattCallBack method and when device is DISCONNECTED, i unpaired it.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
switch (newState) {
case BluetoothProfile.STATE_CONNECTED: {
Preferences.AppLog("Connected to GATT server.");
intentAction = ACTION_GATT_CONNECTED;
broadcastUpdate(intentAction);
mBluetoothGatt.discoverServices();
break;
}
case BluetoothProfile.STATE_DISCONNECTED: {
Preferences.AppLog("Disconnected from GATT server.");
intentAction = ACTION_GATT_DISCONNECTED;
broadcastUpdate(intentAction);
if (gatt.getDevice() != null) {
unpairDevice(gatt.getDevice());
}
break;
}
}
}
}
public static void unpairDevice(BluetoothDevice device) {
try {
Method m = device.getClass().getMethod("removeBond", (Class[]) null);
m.invoke(device, (Object[]) null);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
But still it is not auto reconnect when I bring the device in range.
na...@gmail.com <na...@gmail.com> #29
You still need to call BluetoothDevice.connectGatt() to connect to the device. The approach we had to get around this problem is like this:
1. Once BLE is disconnected (You are out of range), do not remove bond at this point, call getBluetoothLeScanner().startScan() to keep on scanning for your desired device.
2. When you are in range, the desired device BluetoothDevice is found in onScanResult callback.
3. Connect to it, if it fails and give you error code 22 or 133 (some other codes may apply, google didn't document this very well). go to step 4.
3. Now check bonding for this BluetoothDevice whether is bonded or not, always remove old and create a new bonding to it.
4. Now connect to it again.
Problem: phones may pop up bonding dialogue everytime it reconnects.
1. Once BLE is disconnected (You are out of range), do not remove bond at this point, call getBluetoothLeScanner().startScan() to keep on scanning for your desired device.
2. When you are in range, the desired device BluetoothDevice is found in onScanResult callback.
3. Connect to it, if it fails and give you error code 22 or 133 (some other codes may apply, google didn't document this very well). go to step 4.
3. Now check bonding for this BluetoothDevice whether is bonded or not, always remove old and create a new bonding to it.
4. Now connect to it again.
Problem: phones may pop up bonding dialogue everytime it reconnects.
em...@gmail.com <em...@gmail.com> #30
ja...@topsinfosolutions.com: Set the second parameter (autoConnect) to true. That way it will automatically try to reconnect when the device comes back in range. Or use mBluetoothGatt.connect() to also enable autoConnect.
[Deleted User] <[Deleted User]> #31
em...@gmail.com: I have already tried with autoConnect to true but when device comes back in range it call the method , mBluetoothGatt = device.connectGatt(this, true, mGattCallback); but mGattCallback did not return any thing.
ja...@gmail.com <ja...@gmail.com> #32
I'm trying to do the same thing.
What am I missing? Why is it necessary to remove the old bonding if that should be used to identify the device? What is the purpose of bonding then?
What am I missing? Why is it necessary to remove the old bonding if that should be used to identify the device? What is the purpose of bonding then?
mu...@gmail.com <mu...@gmail.com> #33
Hi, any luck on this? am also working on the same case. Please update the thread.
ma...@gmail.com <ma...@gmail.com> #34
ei...@google.com <ei...@google.com>
sa...@google.com <sa...@google.com> #35
Thank you for the feedback. We're closing this issue as Obsolete.
If it is still observed in the latest Android release, please open a new issue inhttps://goo.gl/TbMiIO along with a reference to this issue.
If it is still observed in the latest Android release, please open a new issue in
Description
Symptom:
Request for background connection is sometimes completed as direct connection. In the log below BluetoothGatt#connect() shows auto=true but GattService#clientConnect() shows isDirect=true (isDirect should be !auto).
Analysis:
675 /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
676 if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
677 synchronized(mStateLock) {
678 if (mConnState != CONN_STATE_IDLE) {
679 throw new IllegalStateException("Not idle");
680 }
681 mConnState = CONN_STATE_CONNECTING;
682 }
683 if (!registerApp(callback)) {
684 synchronized(mStateLock) {
685 mConnState = CONN_STATE_IDLE;
686 }
687 Log.e(TAG, "Failed to register callback");
688 return false;
689 }
690
691 // the connection will continue after successful callback registration
692 mAutoConnect = autoConnect;
693 return true;
694 }
There is a race condition between lines 683 and 692. registerApp() causes a callback to happen on onClientRegistered() which calls mService.clientConnect():
127 public void onClientRegistered(int status, int clientIf) {
......
147 mService.clientConnect(mClientIf, mDevice.getAddress(),
148 !mAutoConnect); // autoConnect is inverse of "isDirect"
If autoConnect is set to true and the onClientRegistered() happens before line 692 gets executed the race condition leads to mAutoConnect being uninitialized.
Mitigation:
Only call BluetoothDevice#connectGatt() with autoconnect set to false and use BluetoothGatt#connect() for a background connection.
Log:
05-14 15:55:26.797 D/BluetoothGatt(30538): connect() - device: 11:22:33:44:55:66, auto: true
05-14 15:55:26.797 D/BluetoothGatt(30538): registerApp()
05-14 15:55:26.797 D/BluetoothGatt(30538): registerApp() - UUID=7bed3cba-5bfe-4635-ab37-9f49a436de91
05-14 15:55:26.797 D/BtGatt.GattService( 1350): registerClient() - UUID=7bed3cba-5bfe-4635-ab37-9f49a436de91
05-14 15:55:26.797 D/BtGatt.btif( 1350): btif_gattc_register_app
05-14 15:55:26.797 D/BtGatt.btif( 1350): btgattc_handle_event: Event 1000
05-14 15:55:26.797 D/BtGatt.btif( 1350): btif_gattc_upstreams_evt: Event 0
05-14 15:55:26.797 D/BtGatt.GattService( 1350): onClientRegistered() - UUID=7bed3cba-5bfe-4635-ab37-9f49a436de91, clientIf=5
05-14 15:55:26.797 D/BluetoothGatt(30538): onClientRegistered() - status=0 clientIf=5
05-14 15:55:26.807 D/BtGatt.GattService( 1350): clientConnect() - address=11:22:33:44:55:66, isDirect=true
05-14 15:55:26.807 D/BtGatt.btif( 1350): btif_gattc_open
05-14 15:55:26.807 D/BtGatt.btif( 1350): btgattc_handle_event: Event 1004