14

I have an application that working well on Android 4.3 and 4.4. The application will connect and communicate with a custom bluetooth device.
After I flashed my Nexus 5 to Lollipop suddenly the I can't connect to the device at all. The connection result always 133. This is the log :

D/BluetoothGatt﹕ connect() - device: 00:07:80:04:1A:5A, auto: true
D/BluetoothGatt﹕ registerApp()
D/BluetoothGatt﹕ registerApp() - UUID=xxxxxx-xxxx-xxxxx-xxxx-xxxxxxxx
D/BluetoothGatt﹕ onClientRegistered() - status=0 clientIf=6
D/BluetoothGatt﹕ onClientConnectionState() - status=133 clientIf=6 device=00:07:80:04:1A:5A

My code :

public boolean connect(final String address) {
        if (mBluetoothAdapter == null || address == null) {
            return false;
        }
        Handler handler = new Handler(Looper.getMainLooper());
        // Previously connected device.  Try to reconnect.
        if (mBluetoothDeviceAddress != null
                && address.equals(mBluetoothDeviceAddress)
                && mBluetoothGatt != null) {

            handler.post(new Runnable() {
                @Override
                public void run() {
                    if (mBluetoothGatt.connect()) {
                        mConnectionState = STATE_CONNECTING;
                    }
                }
            });
            if (mConnectionState == STATE_CONNECTING) {
                return true;
            } else {
                return false;
            }
        }

        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            return false;
        }

        handler.post(new Runnable() {
            @Override
            public void run() {
                mBluetoothGatt = device.connectGatt(BluetoothConnectService.this, true, mGattCallback);
            }
        });
        mBluetoothDeviceAddress = address;
        mConnectionState = STATE_CONNECTING;
        return true;
    }

Anybody have any idea about this?

Niko Adrianus Yuwono
  • 11,012
  • 8
  • 42
  • 64

4 Answers4

19

So I figured out that the problem is the Transport choice in Lollipop.
As you can see in here the change in the

BluetoothDevice.connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)

function is calling

BluetoothDevice.connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport)

with transport set to TRANSPORT_AUTO.
In my case because I will always use TRANSPORT_LE (The value is 2)
I tried to call the second method from my code and set the transport to TRANSPORT_LE. For unknown reason I can't call it directly so I'm using reflection to call it. Until now this works fine for me.

            if(TTTUtilities.isLollipopOrAbove()) {
                // Little hack with reflect to use the connect gatt with defined transport in Lollipop
                Method connectGattMethod = null;

                try {
                    connectGattMethod = device.getClass().getMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }

                try {
                    mBluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(device, BluetoothConnectService.this, false, mGattCallback, TRANSPORT_LE);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            } else  {
                mBluetoothGatt = device.connectGatt(BluetoothConnectService.this, true, mGattCallback);
            }

If any of you have question about my answer feel free to ask in the comment.
Thank you.

Community
  • 1
  • 1
Niko Adrianus Yuwono
  • 11,012
  • 8
  • 42
  • 64
  • Thanks kindly for you quick response. I tried your solution on my Nexus 5, 5.0.1, but unfortunatelly it didn't worked for me. I still get onClientConnectionState() - status=133 clientIf=5. Do you have any ideas why it didn't worked for me? – mol Mar 17 '15 at 07:59
  • @mol Mol try to reset the bluetooth cache first via Settings -> Apps -> All -> Bluetooth Share -> Clear Data – Niko Adrianus Yuwono Mar 17 '15 at 08:04
  • Thanks, but it didn't helped either :( – mol Mar 17 '15 at 08:27
  • 2
    the reason why you can't call it directly is @hide – Marian Paździoch Mar 30 '15 at 07:15
  • Works perfect for Nexus, but I still can't connect to S6 :( – Kevin D. Nov 05 '15 at 07:02
  • @NikoYuwono I am facing the issue in connecting BLE device. The device connection taking long time. I am using this code `device.connectGatt( BTService.this, false, mGattCallback);` could you pls suggest something. how to pair device more faster. – Jay Rathod Apr 12 '16 at 07:09
  • I was surprised to see this work on the NVidia Shield tablet. After I used the above code, I got a different connection error, 128, then had to go into Bluetooth settings and "forget" the paired device that I am trying to connect to. Then I could connect successfully. How or why did it even pair in the first place? Perhaps if this was prevented this introspection call would not be necessary. – davidgyoung Mar 02 '17 at 17:55
  • @davidgyoung Hey David! Good work on your Android Beacon Library! Did you ever try to pair with that device before? Might be some cache problem with the device system? – Niko Adrianus Yuwono Mar 03 '17 at 00:46
  • It is possible to call that function directly if you set the min sdk to 23. – Evgeny Erlihman Mar 06 '17 at 20:36
  • @Hrk No It wasn't! but after this hack it worked well – Niko Adrianus Yuwono May 30 '17 at 09:11
  • I am trying to use this example code and can't seem to find the BluetoothConnectService.this. Can anyone tell me how to include that? – user856232 Nov 13 '18 at 14:35
4

For Xamarin users who have the same issue, here is a slightly different solution. I had the same issue with a Nexus 7 Android 6 using the Xamarin cross platform SDK. The use of TRANSPORT_LE fixed the issue. Rather than using Reflection to get the method by its signature (does not work), one can use Reflection to iterate through all the methods until you find a matching name. See code below:

BluetoothDevice bd = (BluetoothDevice)device.NativeDevice;
Java.Lang.Reflect.Method[] methods = bd.Class.GetDeclaredMethods();

foreach (Java.Lang.Reflect.Method possibleConnectGattMethod in methods) 
{
// Find matching method name connectGatt and then invoke it with     TRANSPORT_LE
}
rameshpa
  • 555
  • 5
  • 5
0

I do not think calling connectGatt method youself using reflection is a wise thing. As the private functions can get changed anytime with the update leaves your application buggy.

And anyways TRANSPORT_AUTO should try to connect to your peripheral in a desired way if proper flags are set in your peripheral advertisement packet. If your peripheral does not support TRANSPORT_BREDR mode then there is a standard flag "BrEdrNotSupported" that you should set in advertisement data to let central know about it.

kaps
  • 190
  • 3
  • 9
0

What kind of BLE IC are you using? If it is a CC254x it may be related to problems in their software stack for peripheral devices:

https://e2e.ti.com/support/wireless_connectivity/f/538/t/401240

brndn
  • 521
  • 1
  • 4
  • 18
  • Please use the comments field for this kind of suggestion. Add answers only if you have an actual solution to the problem. – Molx Apr 09 '15 at 21:30
  • 1
    Comments require a 50 reputation account. I don't have that. I still want to help the guy. What am I supposed to do. – brndn Apr 10 '15 at 22:09
  • "[Why does this limit exist](http://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead)? We realize that new users may have valuable comments, and that we may lose some of those contributions by requiring 50 reputation points to unlock the feature. (...) But I want to contribute now. What should I do instead? Can I put my comment in an answer? No." This is how it has to be so SO keep its level of content, even if it costs some good contributions like yours, unfortunately. – Molx Apr 11 '15 at 00:52