diff options
13 files changed, 103 insertions, 44 deletions
diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver.java index c3795b2b..7b163efb 100644 --- a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver.java +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver.java @@ -121,7 +121,15 @@ public class QtBluetoothBroadcastReceiver extends BroadcastReceiver static public boolean setPairingMode(String address, boolean isPairing) { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + BluetoothManager manager = + (BluetoothManager)qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + if (manager == null) + return false; + + BluetoothAdapter adapter = manager.getAdapter(); + if (adapter == null) + return false; + // Uses reflection as the removeBond() is not part of public API try { BluetoothDevice device = adapter.getRemoteDevice(address); diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java index 8f0a0f09..9671f11a 100644 --- a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java @@ -11,6 +11,7 @@ import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothManager; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; @@ -39,7 +40,7 @@ import java.util.UUID; public class QtBluetoothLE { private static final String TAG = "QtBluetoothGatt"; - private final BluetoothAdapter mBluetoothAdapter; + private BluetoothAdapter mBluetoothAdapter = null; private boolean mLeScanRunning = false; private BluetoothGatt mBluetoothGatt = null; @@ -163,14 +164,23 @@ public class QtBluetoothLE { Context qtContext = null; @SuppressWarnings("WeakerAccess") - public QtBluetoothLE() { - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + public QtBluetoothLE(Context context) { + qtContext = context; + + BluetoothManager manager = + (BluetoothManager)qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + if (manager == null) + return; + + mBluetoothAdapter = manager.getAdapter(); + if (mBluetoothAdapter == null) + return; + mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); } public QtBluetoothLE(final String remoteAddress, Context context) { - this(); - qtContext = context; + this(context); mRemoteGattAddress = remoteAddress; } @@ -185,6 +195,11 @@ public class QtBluetoothLE { if (isEnabled == mLeScanRunning) return true; + if (mBluetoothLeScanner == null) { + Log.w(TAG, "Cannot start LE scan, no bluetooth scanner"); + return false; + } + if (isEnabled) { Log.d(TAG, "Attempting to start BTLE scan"); ScanSettings.Builder settingsBuilder = new ScanSettings.Builder(); @@ -682,6 +697,11 @@ public class QtBluetoothLE { public synchronized boolean connect() { BluetoothDevice mRemoteGattDevice; + if (mBluetoothAdapter == null) { + Log.w(TAG, "Cannot connect, no bluetooth adapter"); + return false; + } + try { mRemoteGattDevice = mBluetoothAdapter.getRemoteDevice(mRemoteGattAddress); } catch (IllegalArgumentException ex) { diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java index e8b4bd1f..f595dec0 100644 --- a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java @@ -43,7 +43,7 @@ public class QtBluetoothLEServer { private Context qtContext = null; // Bluetooth members - private final BluetoothAdapter mBluetoothAdapter; + private BluetoothAdapter mBluetoothAdapter = null; private BluetoothManager mBluetoothManager = null; private BluetoothGattServer mGattServer = null; private BluetoothLeAdvertiser mLeAdvertiser = null; @@ -249,16 +249,21 @@ public class QtBluetoothLEServer { public QtBluetoothLEServer(Context context) { qtContext = context; - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - - if (mBluetoothAdapter == null || qtContext == null) { - Log.w(TAG, "Missing Bluetooth adapter or Qt context. Peripheral role disabled."); + if (qtContext == null) { + Log.w(TAG, "Missing context object. Peripheral role disabled."); return; } - mBluetoothManager = (BluetoothManager) qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + mBluetoothManager = + (BluetoothManager) qtContext.getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { - Log.w(TAG, "Bluetooth service not available."); + Log.w(TAG, "Bluetooth service not available. Peripheral role disabled."); + return; + } + + mBluetoothAdapter = mBluetoothManager.getAdapter(); + if (mBluetoothAdapter == null) { + Log.w(TAG, "Missing Bluetooth adapter. Peripheral role disabled."); return; } diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer.java index 4c470a55..cc78c5d7 100644 --- a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer.java +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer.java @@ -5,7 +5,9 @@ package org.qtproject.qt.android.bluetooth; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothServerSocket; +import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothSocket; +import android.content.Context; import android.util.Log; import java.io.IOException; import java.util.UUID; @@ -19,6 +21,8 @@ public class QtBluetoothSocketServer extends Thread long qtObject = 0; @SuppressWarnings({"WeakerAccess", "CanBeFinal"}) public boolean logEnabled = false; + @SuppressWarnings("WeakerAccess") + static Context qtContext = null; private static final String TAG = "QtBluetooth"; private boolean m_isSecure = false; @@ -31,8 +35,9 @@ public class QtBluetoothSocketServer extends Thread private static final int QT_LISTEN_FAILED = 1; private static final int QT_ACCEPT_FAILED = 2; - public QtBluetoothSocketServer() + public QtBluetoothSocketServer(Context context) { + qtContext = context; setName("QtSocketServerThread"); } @@ -46,7 +51,15 @@ public class QtBluetoothSocketServer extends Thread public void run() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + BluetoothManager manager = + (BluetoothManager)qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + + if (manager == null) { + errorOccurred(qtObject, QT_NO_BLUETOOTH_SUPPORTED); + return; + } + + BluetoothAdapter adapter = manager.getAdapter(); if (adapter == null) { errorOccurred(qtObject, QT_NO_BLUETOOTH_SUPPORTED); return; diff --git a/src/bluetooth/android/androidutils.cpp b/src/bluetooth/android/androidutils.cpp index b33275b2..7b7c9cc1 100644 --- a/src/bluetooth/android/androidutils.cpp +++ b/src/bluetooth/android/androidutils.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "androidutils_p.h" +#include "jni_android_p.h" #include <QtCore/QLoggingCategory> #include <QtCore/private/qandroidextras_p.h> @@ -43,4 +44,27 @@ bool ensureAndroidPermission(BluetoothPermission permission) return false; } +QJniObject getDefaultBluetoothAdapter() +{ + QJniObject service = QJniObject::getStaticField<QtJniTypes::AndroidContext, jstring>( + "BLUETOOTH_SERVICE"); + QJniObject context = QNativeInterface::QAndroidApplication::context(); + QJniObject manager = + context.callMethod<jobject>("getSystemService", service.object<jstring>()); + QJniObject adapter; + if (manager.isValid()) + adapter = manager.callMethod<QtJniTypes::BluetoothAdapter>("getAdapter"); + + // ### Qt 7 check if the below double-get of the adapter can be removed. + // It is a workaround for QTBUG-57489, fixed in 2016. According to the bug it occurred on + // a certain device running Android 6.0.1 (Qt 6 supports Android 6.0 as the minimum). + // For completeness: the original workaround was for the deprecated getDefaultAdapter() + // method, and it is thus unclear if this is needed even in Qt 6 anymore. In addition the + // impacted device is updateable to Android 8 which may also have fixed the issue. + if (!adapter.isValid()) + adapter = manager.callMethod<QtJniTypes::BluetoothAdapter>("getAdapter"); + + return adapter; +} + QT_END_NAMESPACE diff --git a/src/bluetooth/android/androidutils_p.h b/src/bluetooth/android/androidutils_p.h index a28a0fd5..9912ad38 100644 --- a/src/bluetooth/android/androidutils_p.h +++ b/src/bluetooth/android/androidutils_p.h @@ -16,6 +16,7 @@ // #include <qglobal.h> +#include <QtCore/QJniObject> #include <QtCore/QString> QT_BEGIN_NAMESPACE @@ -30,6 +31,9 @@ enum class BluetoothPermission { // Returns true if permission is successfully authorized bool ensureAndroidPermission(BluetoothPermission permission); +// Returns the default bluetooth adapter, or an invalid object if not available +QJniObject getDefaultBluetoothAdapter(); + QT_END_NAMESPACE #endif // QANDROIDBLUETOOTHUTILS_H diff --git a/src/bluetooth/android/jni_android_p.h b/src/bluetooth/android/jni_android_p.h index d4da9075..e172f637 100644 --- a/src/bluetooth/android/jni_android_p.h +++ b/src/bluetooth/android/jni_android_p.h @@ -41,12 +41,14 @@ Q_DECLARE_JNI_CLASS(BluetoothGattDescriptor, "android/bluetooth/BluetoothGattDes Q_DECLARE_JNI_CLASS(BluetoothGattCharacteristic, "android/bluetooth/BluetoothGattCharacteristic") Q_DECLARE_JNI_CLASS(BluetoothDevice, "android/bluetooth/BluetoothDevice") Q_DECLARE_JNI_CLASS(IntentFilter, "android/content/IntentFilter") +Q_DECLARE_JNI_CLASS(AndroidContext, "android/content/Context") Q_DECLARE_JNI_CLASS(UUID, "java/util/UUID") Q_DECLARE_JNI_TYPE(ParcelableArray, "[Landroid/os/Parcelable;") Q_DECLARE_JNI_TYPE(ParcelUuidArray, "[Landroid/os/ParcelUuid;") Q_DECLARE_JNI_TYPE(StringArray, "[Ljava/lang/String;") +Q_DECLARE_JNI_TYPE(BluetoothManager, "Landroid/bluetooth/BluetoothManager;") Q_DECLARE_JNI_TYPE(AdvertiseData, "Landroid/bluetooth/le/AdvertiseData;") Q_DECLARE_JNI_TYPE(AdvertiseSettings, "Landroid/bluetooth/le/AdvertiseSettings;") Q_DECLARE_JNI_TYPE(InputStream, "Ljava/io/InputStream;") diff --git a/src/bluetooth/android/serveracceptancethread.cpp b/src/bluetooth/android/serveracceptancethread.cpp index e9dc06ed..c96fce89 100644 --- a/src/bluetooth/android/serveracceptancethread.cpp +++ b/src/bluetooth/android/serveracceptancethread.cpp @@ -73,7 +73,8 @@ void ServerAcceptanceThread::run() shutdownPendingConnections(); } - javaThread = QJniObject::construct<QtJniTypes::QtBtSocketServer>(); + javaThread = QJniObject::construct<QtJniTypes::QtBtSocketServer>( + QNativeInterface::QAndroidApplication::context()); if (!javaThread.isValid()) return; diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp index 3981954c..cd6327f5 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp @@ -33,8 +33,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( deviceDiscoveryStartAttemptsLeft(deviceDiscoveryStartMaxAttempts), q_ptr(parent) { - adapter = QJniObject::callStaticMethod<QtJniTypes::BluetoothAdapter>( - QtJniTypes::className<QtJniTypes::BluetoothAdapter>(), "getDefaultAdapter"); + adapter = getDefaultBluetoothAdapter(); if (!adapter.isValid()) qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; @@ -419,7 +418,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startLowEnergyScan() m_active = BtleScanActive; if (!leScanner.isValid()) { - leScanner = QJniObject::construct<QtJniTypes::QtBtLECentral>(); + leScanner = QJniObject::construct<QtJniTypes::QtBtLECentral>( + QNativeInterface::QAndroidApplication::context()); if (!leScanner.isValid()) { qCWarning(QT_BT_ANDROID) << "Cannot load BTLE device scan class"; m_active = NoScanActive; diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp index f2415013..ca7faed0 100644 --- a/src/bluetooth/qbluetoothlocaldevice_android.cpp +++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp @@ -46,23 +46,10 @@ QJniObject *QBluetoothLocalDevicePrivate::adapter() return obj; } -static QJniObject getDefaultAdapter() -{ - QJniObject adapter = QJniObject::callStaticMethod<QtJniTypes::BluetoothAdapter>( - QtJniTypes::className<QtJniTypes::BluetoothAdapter>(), "getDefaultAdapter"); - - if (!adapter.isValid()) { - // on some BT implementations the first call to getDefaultAdapter() may fail - adapter = QJniObject::callStaticMethod<QtJniTypes::BluetoothAdapter>( - QtJniTypes::className<QtJniTypes::BluetoothAdapter>(), - "getDefaultAdapter"); - } - return adapter; -} - void QBluetoothLocalDevicePrivate::initialize(const QBluetoothAddress &address) { - QJniObject adapter = getDefaultAdapter(); + QJniObject adapter = getDefaultBluetoothAdapter(); + if (!adapter.isValid()) { qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; return; @@ -309,7 +296,7 @@ QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices() // Android only supports max of one device (so far) QList<QBluetoothHostInfo> localDevices; - QJniObject o = getDefaultAdapter(); + QJniObject o = getDefaultBluetoothAdapter(); if (o.isValid()) { QBluetoothHostInfo info; info.setName(o.callMethod<jstring>("getName").toString()); diff --git a/src/bluetooth/qbluetoothserver_android.cpp b/src/bluetooth/qbluetoothserver_android.cpp index 221bf0f3..3449542b 100644 --- a/src/bluetooth/qbluetoothserver_android.cpp +++ b/src/bluetooth/qbluetoothserver_android.cpp @@ -132,8 +132,7 @@ bool QBluetoothServer::listen(const QBluetoothAddress &localAdapter, quint16 por return false; //check Bluetooth is available and online - QJniObject btAdapter = QJniObject::callStaticMethod<QtJniTypes::BluetoothAdapter>( - QtJniTypes::className<QtJniTypes::BluetoothAdapter>(), "getDefaultAdapter"); + QJniObject btAdapter = getDefaultBluetoothAdapter(); if (!btAdapter.isValid()) { qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp index e3fa662b..f160eb75 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp @@ -58,10 +58,8 @@ QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( The logic below must change once there is more than one adapter. */ - if (createAdapter) { - btAdapter = QJniObject::callStaticMethod<QtJniTypes::BluetoothAdapter>( - QtJniTypes::className<QtJniTypes::BluetoothAdapter>(), "getDefaultAdapter"); - } + if (createAdapter) + btAdapter = getDefaultBluetoothAdapter(); if (!btAdapter.isValid()) qCWarning(QT_BT_ANDROID) << "Platform does not support Bluetooth"; diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp index b1f90822..754f223d 100644 --- a/src/bluetooth/qbluetoothsocket_android.cpp +++ b/src/bluetooth/qbluetoothsocket_android.cpp @@ -143,9 +143,7 @@ QBluetoothSocketPrivateAndroid::QBluetoothSocketPrivateAndroid() inputThread(0) { secFlags = QBluetooth::Security::Secure; - adapter = QJniObject::callStaticMethod<QtJniTypes::BluetoothAdapter>( - QtJniTypes::className<QtJniTypes::BluetoothAdapter>(), "getDefaultAdapter"); - + adapter = getDefaultBluetoothAdapter(); qRegisterMetaType<QBluetoothSocket::SocketError>(); qRegisterMetaType<QBluetoothSocket::SocketState>(); } |