diff options
Diffstat (limited to 'src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp')
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp | 93 |
1 files changed, 79 insertions, 14 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp index be9a4e31..411e7a2b 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp @@ -66,6 +66,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( leScanTimeout(0), pendingCancel(false), pendingStart(false), + lowEnergySearchTimeout(25000), q_ptr(parent) { adapter = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter", @@ -93,8 +94,16 @@ bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const return m_active != NoScanActive; } -void QBluetoothDeviceDiscoveryAgentPrivate::start() +QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods() { + return (LowEnergyMethod | ClassicMethod); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods) +{ + //TODO Implement discovery method handling (see input parameter) + requestedMethods = methods; + if (pendingCancel) { pendingStart = true; return; @@ -128,6 +137,32 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start() return; } + // check Android v23+ permissions + // -> BTLE search requires android.permission.ACCESS_COARSE_LOCATION + if (requestedMethods && QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) { + QString permission(QLatin1String("android.permission.ACCESS_COARSE_LOCATION")); + + // do we have required permission already, if so nothing to do + if (QtAndroidPrivate::checkPermission(permission) == QtAndroidPrivate::PermissionsResult::Denied) { + qCWarning(QT_BT_ANDROID) << "Requesting ACCESS_COARSE_LOCATION permission"; + + QAndroidJniEnvironment env; + const QHash<QString, QtAndroidPrivate::PermissionsResult> results = + QtAndroidPrivate::requestPermissionsSync(env, QStringList() << permission); + if (!results.contains(permission) + || results[permission] == QtAndroidPrivate::PermissionsResult::Denied) + { + qCWarning(QT_BT_ANDROID) << "Search not possible due to missing permission (ACCESS_COARSE_LOCATION)"; + lastError = QBluetoothDeviceDiscoveryAgent::UnknownError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Missing Location permission. Search is not possible"); + emit q->error(lastError); + return; + } + } + + qCWarning(QT_BT_ANDROID) << "ACCESS_COARSE_LOCATION permission available"; + } + // install Java BroadcastReceiver if (!receiver) { // SDP based device discovery @@ -140,18 +175,35 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start() discoveredDevices.clear(); - const bool success = adapter.callMethod<jboolean>("startDiscovery"); - if (!success) { - lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; - errorString = QBluetoothDeviceDiscoveryAgent::tr("Discovery cannot be started"); - emit q->error(lastError); - return; - } + // by arbitrary definition we run classic search first + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) { + const bool success = adapter.callMethod<jboolean>("startDiscovery"); + if (!success) { + lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Classic Discovery cannot be started"); + emit q->error(lastError); + return; + } - m_active = SDPScanActive; + m_active = SDPScanActive; + qCDebug(QT_BT_ANDROID) + << "QBluetoothDeviceDiscoveryAgentPrivate::start() - Classic search successfully started."; + } else { + // LE search only requested + Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); - qCDebug(QT_BT_ANDROID) - << "QBluetoothDeviceDiscoveryAgentPrivate::start() - successfully executed."; + if (QtAndroidPrivate::androidSdkVersion() < 18) { + qCDebug(QT_BT_ANDROID) << "Skipping Bluetooth Low Energy device scan due to" + "insufficient Android version."; + m_active = NoScanActive; + lastError = QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Low Energy Discovery not supported"); + emit q->error(lastError); + return; + } + + startLowEnergyScan(); + } } void QBluetoothDeviceDiscoveryAgentPrivate::stop() @@ -192,7 +244,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::processSdpDiscoveryFinished() emit q->canceled(); } else if (pendingStart) { pendingStart = pendingCancel = false; - start(); + start(requestedMethods); } else { // check that it didn't finish due to turned off Bluetooth Device const int state = adapter.callMethod<jint>("getState"); @@ -204,6 +256,13 @@ void QBluetoothDeviceDiscoveryAgentPrivate::processSdpDiscoveryFinished() return; } + // no BTLE scan requested + if (!(requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)) { + m_active = NoScanActive; + emit q->finished(); + return; + } + // start LE scan if supported if (QtAndroidPrivate::androidSdkVersion() < 18) { qCDebug(QT_BT_ANDROID) << "Skipping Bluetooth Low Energy device scan"; @@ -285,15 +344,21 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startLowEnergyScan() return; } + // wait interval and sum up what was found if (!leScanTimeout) { leScanTimeout = new QTimer(this); leScanTimeout->setSingleShot(true); - leScanTimeout->setInterval(25000); connect(leScanTimeout, &QTimer::timeout, this, &QBluetoothDeviceDiscoveryAgentPrivate::stopLowEnergyScan); } - leScanTimeout->start(); + if (lowEnergySearchTimeout > 0) { // otherwise no timeout and stop() required + leScanTimeout->setInterval(lowEnergySearchTimeout); + leScanTimeout->start(); + } + + qCDebug(QT_BT_ANDROID) + << "QBluetoothDeviceDiscoveryAgentPrivate::start() - Low Energy search successfully started."; } void QBluetoothDeviceDiscoveryAgentPrivate::stopLowEnergyScan() |