From 76d98250d46b4afa3d83b550bd26b33021928310 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Wed, 19 Feb 2020 09:40:57 +0100 Subject: Catch turned off Bluetooth adapter when stopping LE discovery Calling stopLeScan() causes a runtime exception. The patch prevents a crash due to the exception and progresses as if nothing has happened. An action that turned off the internal Bluetooth device has stopped a runnung discovery anyway. Fixes: QTBUG-67482 Change-Id: Iff377884c50cafa1f74dafe73e0acbb31b13e9bb Reviewed-by: Timur Pocheptsov --- .../src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 8a69b4c7..f70ee8a4 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 @@ -162,7 +162,13 @@ public class QtBluetoothLE { mBluetoothLeScanner.startScan(filterList, settings, leScanCallback21); mLeScanRunning = true; } else { - mBluetoothLeScanner.stopScan(leScanCallback21); + try { + mBluetoothLeScanner.stopScan(leScanCallback21); + } catch (IllegalStateException isex) { + // when trying to stop a scan while bluetooth is offline + // java.lang.IllegalStateException: BT Adapter is not turned ON + Log.d(TAG, "Stopping LE scan not possible: " + isex.getMessage()); + } mLeScanRunning = false; } -- cgit v1.2.3 From fd48361a193889cdc25af8aeb311acc8ad85fa26 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Wed, 12 Feb 2020 14:57:41 +0100 Subject: Add location-turned-on check before starting device discovery The location permission and a running location service have been a prerequisite for a successful LE scan since Android v23. While the permission has always been checked before doing a bluetooth scan, the state of the location service was not checked. LE discovery without location turned on does not error out. It just reports zero discoveries. Starting with Android SDK v29, a classic Bluetooth discovery requires a running Location service too. Due to BluetoothAdapater.startDiscovery() returning an error code when location is turned off, it was time to check the location service before triggering the discovery to simplify the error handling for the API user. This patch ensures that location is turned on before any type of device discovery is started and the API reports an error reflecting this problem. Task-number: QTBUG-81875 Change-Id: Id51fd502ae24cbadbc704451fdf49d999224c16f Reviewed-by: Konstantin Ritt Reviewed-by: Oliver Wolff --- .../qbluetoothdevicediscoveryagent_android.cpp | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp index d8cc5ace..4b9e2032 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp @@ -185,6 +185,44 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent qCWarning(QT_BT_ANDROID) << "ACCESS_COARSE|FINE_LOCATION permission available"; } + // Double check Location service is turned on + bool locationTurnedOn = true; // backwards compatible behavior to previous Qt versions + const QAndroidJniObject locString = QAndroidJniObject::getStaticObjectField( + "android/content/Context", "LOCATION_SERVICE", "Ljava/lang/String;"); + const QAndroidJniObject locService = QtAndroid::androidContext().callObjectMethod( + "getSystemService", + "(Ljava/lang/String;)Ljava/lang/Object;", + locString.object()); + + if (locService.isValid()) { + if (QtAndroid::androidSdkVersion() >= 28) { + locationTurnedOn = bool(locService.callMethod("isLocationEnabled")); + } else { + // try GPS and network provider + QAndroidJniObject provider = QAndroidJniObject::getStaticObjectField( + "android/location/LocationManager", "GPS_PROVIDER", "Ljava/lang/String;"); + bool gpsTurnedOn = bool(locService.callMethod("isProviderEnabled", + "(Ljava/lang/String;)Z", provider.object())); + + provider = QAndroidJniObject::getStaticObjectField( + "android/location/LocationManager", "NETWORK_PROVIDER", "Ljava/lang/String;"); + bool providerTurnedOn = bool(locService.callMethod("isProviderEnabled", + "(Ljava/lang/String;)Z", provider.object())); + + locationTurnedOn = gpsTurnedOn || providerTurnedOn; + } + } + + if (!locationTurnedOn) { + qCWarning(QT_BT_ANDROID) << "Search not possible due to turned off Location service"; + lastError = QBluetoothDeviceDiscoveryAgent::UnknownError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Location service turned off. Search is not possible."); + emit q->error(lastError); + return; + } + + qCDebug(QT_BT_ANDROID) << "Location turned on"; + // install Java BroadcastReceiver if (!receiver) { // SDP based device discovery -- cgit v1.2.3 From c81430b704e17d2f2eb5445e261ab3753bef3328 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Wed, 12 Feb 2020 15:50:37 +0100 Subject: Ensure that a failing classic discovery doesn't prevent LE scan When the classic scan does not start properly we immediately error out. If the user has requested LE discovery in addition to the classic discovery, we should continue with LE discovery. By convention, we only bother the user with an error signal if none of the two methods succeed. Task-number: QTBUG-81875 Change-Id: Id867892210fbef6da0e4937c2aef20f726ba9a2a Reviewed-by: Konstantin Ritt Reviewed-by: Timur Pocheptsov --- .../qbluetoothdevicediscoveryagent_android.cpp | 24 ++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp index 4b9e2032..fd17faee 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp @@ -239,17 +239,25 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) { const bool success = adapter.callMethod("startDiscovery"); if (!success) { - lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; - errorString = QBluetoothDeviceDiscoveryAgent::tr("Classic Discovery cannot be started"); - emit q->error(lastError); + qCDebug(QT_BT_ANDROID) << "Classic Discovery cannot be started"; + if (requestedMethods == QBluetoothDeviceDiscoveryAgent::ClassicMethod) { + //only classic discovery requested -> error out + lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Classic Discovery cannot be started"); + + emit q->error(lastError); + return; + } // else fall through to LE discovery + } else { + m_active = SDPScanActive; + qCDebug(QT_BT_ANDROID) + << "QBluetoothDeviceDiscoveryAgentPrivate::start() - Classic search successfully started."; return; } + } - m_active = SDPScanActive; - qCDebug(QT_BT_ANDROID) - << "QBluetoothDeviceDiscoveryAgentPrivate::start() - Classic search successfully started."; - } else { - // LE search only requested + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) { + // LE search only requested or classic discovery failed but lets try LE scan anyway Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); if (QtAndroidPrivate::androidSdkVersion() < 18) { -- cgit v1.2.3 From 0c8f3eb35eead6e4db7732020d7fb2863ba3787f Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Wed, 12 Feb 2020 16:18:51 +0100 Subject: Grant ACCESS_FINE_LOCATION to QtBluetooth Since Android 10(SDK v29+) all types of Bluetooth device discovery require ACCESS_FINE_LOCATION. This is highlighted by https://developer.android.com/about/versions/10/privacy/changes#location-telephony-bluetooth-wifi Fixes: QTBUG-81875 Change-Id: Icaecca1f72a994dc774dc2b90194da15cc0787b0 Reviewed-by: Konstantin Ritt Reviewed-by: Timur Pocheptsov Reviewed-by: Oliver Wolff --- src/bluetooth/bluetooth.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro index e1e4d7a2..4d181dfb 100644 --- a/src/bluetooth/bluetooth.pro +++ b/src/bluetooth/bluetooth.pro @@ -139,6 +139,7 @@ qtConfig(bluez) { ANDROID_PERMISSIONS = \ android.permission.BLUETOOTH \ android.permission.BLUETOOTH_ADMIN \ + android.permission.ACCESS_FINE_LOCATION \ android.permission.ACCESS_COARSE_LOCATION # since Android 6.0 (API lvl 23) ANDROID_BUNDLED_JAR_DEPENDENCIES = \ jar/QtAndroidBluetooth.jar:org.qtproject.qt5.android.bluetooth.QtBluetoothBroadcastReceiver -- cgit v1.2.3 From a2769b323dc890def9dffaf98c768cec12eba3c0 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Wed, 12 Feb 2020 15:54:48 +0100 Subject: Suppress deployment-settings files on Android Apparently the file name convention has slightly changed. Change-Id: Iab220cc2350ee3a43c11a03ea76b1e2f33e53674 Reviewed-by: Konstantin Ritt Reviewed-by: Timur Pocheptsov Reviewed-by: Oliver Wolff --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1b9be3d7..881b5b8a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,7 @@ moc_*.cpp ui_*.h qrc_*.cpp *.moc -*so-deployment-settings.json +*deployment-settings.json .qmake.cache .pch QtBluetooth.version* -- cgit v1.2.3