diff options
Diffstat (limited to 'src/corelib/kernel/qpermissions_android.cpp')
-rw-r--r-- | src/corelib/kernel/qpermissions_android.cpp | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/src/corelib/kernel/qpermissions_android.cpp b/src/corelib/kernel/qpermissions_android.cpp index 25ae111bec..6c21ded72c 100644 --- a/src/corelib/kernel/qpermissions_android.cpp +++ b/src/corelib/kernel/qpermissions_android.cpp @@ -49,6 +49,34 @@ static QStringList nativeLocationPermission(const QLocationPermission &permissio return nativeLocationPermissionList; } +static QStringList nativeBluetoothPermission(const QBluetoothPermission &permission) +{ + // See https://developer.android.com/guide/topics/connectivity/bluetooth/permissions + // for the details. + + // API Level < 31 + static QString bluetoothGeneral = u"android.permission.BLUETOOTH"_s; + // API Level >= 31 + static QString bluetoothScan = u"android.permission.BLUETOOTH_SCAN"_s; + static QString bluetoothAdvertise = u"android.permission.BLUETOOTH_ADVERTISE"_s; + static QString bluetoothConnect = u"android.permission.BLUETOOTH_CONNECT"_s; + // Fine location is currently required for ALL API levels, but that is not + // strictly necessary for API Level >= 31. See QTBUG-112164. + static QString fineLocation = u"android.permission.ACCESS_FINE_LOCATION"_s; + + if (QtAndroidPrivate::androidSdkVersion() < 31) { + return {bluetoothGeneral, fineLocation}; + } else { + const auto modes = permission.communicationModes(); + QStringList permissionList; + if (modes & QBluetoothPermission::Advertise) + permissionList << bluetoothAdvertise; + if (modes & QBluetoothPermission::Access) + permissionList << bluetoothScan << bluetoothConnect << fineLocation; + return permissionList; + } +} + static QStringList nativeStringsFromPermission(const QPermission &permission) { const auto id = permission.type().id(); @@ -59,8 +87,7 @@ static QStringList nativeStringsFromPermission(const QPermission &permission) } else if (id == qMetaTypeId<QMicrophonePermission>()) { return { u"android.permission.RECORD_AUDIO"_s }; } else if (id == qMetaTypeId<QBluetoothPermission>()) { - // TODO: handle Android 12 new bluetooth permissions - return { u"android.permission.BLUETOOTH"_s }; + return nativeBluetoothPermission(*permission.value<QBluetoothPermission>()); } else if (id == qMetaTypeId<QContactsPermission>()) { const auto readContactsString = u"android.permission.READ_CONTACTS"_s; switch (permission.value<QContactsPermission>()->accessMode()) { @@ -104,6 +131,18 @@ Q_GLOBAL_STATIC_WITH_ARGS(PermissionStatusHash, g_permissionStatusHash, ({ { qMetaTypeId<QLocationPermission>(), Qt::PermissionStatus::Undetermined } })); +static Qt::PermissionStatus +getCombinedStatus(const QList<QtAndroidPrivate::PermissionResult> &androidResults) +{ + // Android returns only Denied or Granted + for (const auto &result : androidResults) { + const auto status = permissionStatusForAndroidResult(result); + if (status == Qt::PermissionStatus::Denied) + return status; + } + return Qt::PermissionStatus::Granted; +} + namespace QPermissions::Private { Qt::PermissionStatus checkPermission(const QPermission &permission) @@ -112,8 +151,12 @@ namespace QPermissions::Private if (nativePermissionList.isEmpty()) return Qt::PermissionStatus::Granted; - const auto result = QtAndroidPrivate::checkPermission(nativePermissionList.first()).result(); - const auto status = permissionStatusForAndroidResult(result); + QList<QtAndroidPrivate::PermissionResult> androidResults; + androidResults.reserve(nativePermissionList.size()); + for (const auto &nativePermission : nativePermissionList) + androidResults.push_back(QtAndroidPrivate::checkPermission(nativePermission).result()); + + const auto status = getCombinedStatus(androidResults); const auto it = g_permissionStatusHash->constFind(permission.type().id()); const bool foundStatus = (it != g_permissionStatusHash->constEnd()); const bool itUndetermined = foundStatus && (*it) == Qt::PermissionStatus::Undetermined; @@ -133,8 +176,9 @@ namespace QPermissions::Private QtAndroidPrivate::requestPermissions(nativePermissionList).then(qApp, [callback, permission](QFuture<QtAndroidPrivate::PermissionResult> future) { - const auto result = future.isValid() ? future.result() : QtAndroidPrivate::Denied; - const auto status = permissionStatusForAndroidResult(result); + const auto androidResults = future.isValid() ? future.results() + : QList{QtAndroidPrivate::Denied}; + const auto status = getCombinedStatus(androidResults); g_permissionStatusHash->insert(permission.type().id(), status); callback(status); } |