diff options
author | Alex Blasche <alexander.blasche@qt.io> | 2016-12-14 17:03:13 +0100 |
---|---|---|
committer | Alex Blasche <alexander.blasche@qt.io> | 2017-01-13 14:19:11 +0000 |
commit | 8690dd6d59831206736b3a7839d8d3fd14251362 (patch) | |
tree | 73cb50ed9292f187f5a7b81a225af18f5db58e4a /src | |
parent | 096a4694427d34dd3a0ce5a7aeb8d2011fb96c8b (diff) |
Improve likelyhood that BluetoothGatt.connectGatt succeeds
The dreaded GATT_ERROR 133 (0x85) is a long standing issue in Android.
There have been continued efforts to reduce it up until Android N:
https://code.google.com/p/android/issues/detail?id=192561
Tests have shown that the new BluetoothGatt.connectGatt() overload
is much more reliable. Android v23+ gets some relief and Android v21+
gets unofficial/hidden relief.
Reports indicate that error 133 is timeing related. While the new
connectGatt() call seems to resolve this problem it is throwing
the timeing related error 22 more proactively. Very quick
connect()/disconnect()/connect() calls can cause the error. The patch
adds a more specific error code handling for error 22 to provide
some hints on what the user can do to prevent it.
Task-number: QTBUG-56078
Change-Id: Ib14d503701cee7ea766247b712106302cba896f3
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java index 3348e4de..b375f00e 100644 --- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java +++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java @@ -51,6 +51,7 @@ import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.Log; +import java.lang.reflect.Method; import java.util.concurrent.atomic.AtomicInteger; import java.util.ArrayList; @@ -185,9 +186,11 @@ public class QtBluetoothLE { case BluetoothGatt.GATT_SUCCESS: errorCode = 0; break; //QLowEnergyController::NoError case 8: // link loss + case 22: // BTA_GATT_CONN_LMP_TIMEOUT + Log.w(TAG, "Connection Error: Try to delay connect() call after previous activity"); errorCode = 5; break; //QLowEnergyController::ConnectionError default: - Log.w(TAG, "Unhandled error code on connectionStateChanged: " + status); + Log.w(TAG, "Unhandled error code on connectionStateChanged: " + status + " " + newState); errorCode = status; break; //TODO deal with all errors } leConnectionStateChange(qtObject, errorCode, qLowEnergyController_State); @@ -477,7 +480,31 @@ public class QtBluetoothLE { return false; } - mBluetoothGatt = mRemoteGattDevice.connectGatt(qtContext, false, gattCallback); + try { + // BluetoothDevice.,connectGatt(Context, boolean, BluetoothGattCallback, int) was + // officially introduced by Android API v23. Earlier Android versions have a private + // implementation already though. Let's check at runtime and use it if possible. + // + // In general the new connectGatt() seems to be much more reliable than the function + // that doesn't specify the transport layer. + + Class[] args = new Class[4]; + args[0] = android.content.Context.class; + args[1] = boolean.class; + args[2] = android.bluetooth.BluetoothGattCallback.class; + args[3] = int.class; + Method connectMethod = mRemoteGattDevice.getClass().getDeclaredMethod("connectGatt", args); + if (connectMethod != null) { + mBluetoothGatt = (BluetoothGatt) connectMethod.invoke(mRemoteGattDevice, qtContext, + false, gattCallback, + 2 /*TRANSPORT_LE*/); + Log.w(TAG, "Using Android v23 BluetoothDevice.connectGatt()"); + } + } catch (Exception ex) { + // fallback to less reliable API 18 version + mBluetoothGatt = mRemoteGattDevice.connectGatt(qtContext, false, gattCallback); + } + return mBluetoothGatt != null; } |