From 1969a25ceef1be7b9769245054c80e5b56491820 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Wed, 30 Jun 2021 14:48:10 +0300 Subject: [PATCH] Simplify the application permission API Remove read/write variants of the permission types to make the API simpler and more versatile. If the user wishes to have more control over the permission requests/checks, they can use more platform-specific code. Pick-to: 6.2 Task-number: QTBUG-94407 Change-Id: I2b72041aa3effaac7e7f7361237cf1146817b525 Reviewed-by: Edward Welbourne --- src/corelib/kernel/qapplicationpermission.h | 18 ++-- .../kernel/qapplicationpermission.qdoc | 27 +++--- .../kernel/qcoreapplication_android.cpp | 87 ++++++++++--------- 3 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/corelib/kernel/qapplicationpermission.h b/src/corelib/kernel/qapplicationpermission.h index 35b0d5beef..1e09b03fc3 100644 --- a/src/corelib/kernel/qapplicationpermission.h +++ b/src/corelib/kernel/qapplicationpermission.h @@ -51,25 +51,23 @@ enum PermissionType { Camera, Microphone, Bluetooth, - CoarseLocation, + Location, PreciseLocation, - CoarseBackgroundLocation, + BackgroundLocation, PreciseBackgroundLocation, BodySensors, PhysicalActivity, - ReadContacts, - WriteContacts, - ReadStorage, + Contacts, + Storage, + // TODO: remove after usages in other modules are renamed. WriteStorage, - ReadCalendar, - WriteCalendar + Calendar }; enum PermissionResult { + Undetermined, Authorized, - Denied, - Restricted, - Undetermined + Denied }; } // QApplicationPermission diff --git a/src/corelib/kernel/qapplicationpermission.qdoc b/src/corelib/kernel/qapplicationpermission.qdoc index fee02b634f..7e2bcaad91 100644 --- a/src/corelib/kernel/qapplicationpermission.qdoc +++ b/src/corelib/kernel/qapplicationpermission.qdoc @@ -45,7 +45,7 @@ \value Microphone Access the microphone, receive the sound signal (e.g. to analyze or record it). Maps to \c "android.permission.RECORD_AUDIO" on Android. - \value CoarseLocation Access approximate location provider (wifi, cell tower). + \value Location Access approximate location provider (wifi, cell tower). Maps to \c "android.permission.ACCESS_COARSE_LOCATION" on Android. \value PreciseLocation Location Access accurate location provider (satellite). Maps to \c "android.permission.ACCESS_FINE_LOCATION" on Android. @@ -53,27 +53,24 @@ the app is in the background. Maps to \c "android.permission.ACCESS_BACKGROUND_LOCATION" on Android, and implies \l PreciseLocation. - \value CoarseBackgroundLocation Access the approximate location services when + \value BackgroundLocation Access the approximate location services when the app is in the background. Maps to \c "android.permission.ACCESS_BACKGROUND_LOCATION" on Android, and - implies \l CoarseLocation. + implies \l Location. \value BodySensors Access body sensors such as a heart rate sensor. Maps to \c "android.permission.BODY_SENSORS" on Android. \value PhysicalActivity Access to data about physical activity and body movements. Maps to \c "android.permission.ACTIVITY_RECOGNITION" on Android. - \value ReadContacts Read user contacts. Maps to - \c "android.permission.READ_CONTACTS" on Android. - \value WriteContacts Write user contacts. Maps to - \c "android.permission.WRITE_CONTACTS" on Android. - \value ReadStorage Access device storage with read permissions. - Maps to \c "android.permission.READ_EXTERNAL_STORAGE" on Android. - \value WriteStorage Access device storage with write permissions. - Maps to \c "android.permission.WRITE_EXTERNAL_STORAGE" on Android. - \value ReadCalendar Read the user's calendar. - Maps to \c "android.permission.READ_CALENDAR" on Android. - \value WriteCalendar Write to the user's calendar. - Maps to \c "android.permission.WRITE_CALENDAR" on Android. + \value Contacts Read and write user contacts. Maps to + \c "android.permission.READ_CONTACTS" and \c "android.permission.WRITE_CONTACTS" + on Android. + \value Storage Access device storage with read and write permissions. + Maps to \c "android.permission.READ_EXTERNAL_STORAGE" and + \c "android.permission.WRITE_EXTERNAL_STORAGE"on Android. + \value Calendar Read and write the user's calendar. + Maps to \c "android.permission.READ_CALENDAR" and + \c "android.permission.WRITE_CALENDAR" on Android. \omitvalue Bluetooth diff --git a/src/corelib/kernel/qcoreapplication_android.cpp b/src/corelib/kernel/qcoreapplication_android.cpp index b960aebf58..f44b202475 100644 --- a/src/corelib/kernel/qcoreapplication_android.cpp +++ b/src/corelib/kernel/qcoreapplication_android.cpp @@ -83,17 +83,19 @@ static QStringList nativeStringsFromPermission(QApplicationPermission::Permissio QStringLiteral("android.permission.ACCESS_BACKGROUND_LOCATION"); switch (permission) { - case QApplicationPermission::CoarseLocation: + case QApplicationPermission::Location: return {coarsePerm}; case QApplicationPermission::PreciseLocation: return {precisePerm}; - case QApplicationPermission::CoarseBackgroundLocation: + case QApplicationPermission::BackgroundLocation: // Keep the background permission first to be able to use .first() // in checkPermission because it takes single permission if (QtAndroidPrivate::androidSdkVersion() >= 29) return {backgroundPerm, coarsePerm}; return {coarsePerm}; case QApplicationPermission::PreciseBackgroundLocation: + // Keep the background permission first to be able to use .first() + // in checkPermission because it takes single permission if (QtAndroidPrivate::androidSdkVersion() >= 29) return {backgroundPerm, precisePerm}; return {precisePerm}; @@ -101,26 +103,24 @@ static QStringList nativeStringsFromPermission(QApplicationPermission::Permissio return {QStringLiteral("android.permission.CAMERA")}; case QApplicationPermission::Microphone: return {QStringLiteral("android.permission.RECORD_AUDIO")}; + case QApplicationPermission::Bluetooth: + return { QStringLiteral("android.permission.BLUETOOTH") }; case QApplicationPermission::BodySensors: return {QStringLiteral("android.permission.BODY_SENSORS")}; case QApplicationPermission::PhysicalActivity: return {QStringLiteral("android.permission.ACTIVITY_RECOGNITION")}; - case QApplicationPermission::ReadContacts: - return {QStringLiteral("android.permission.READ_CONTACTS")}; - case QApplicationPermission::WriteContacts: - return {QStringLiteral("android.permission.WRITE_CONTACTS")}; - case QApplicationPermission::ReadStorage: - return {QStringLiteral("android.permission.READ_EXTERNAL_STORAGE")}; - case QApplicationPermission::WriteStorage: - return {QStringLiteral("android.permission.WRITE_EXTERNAL_STORAGE")}; - case QApplicationPermission::ReadCalendar: - return {QStringLiteral("android.permission.READ_CALENDAR")}; - case QApplicationPermission::WriteCalendar: - return {QStringLiteral("android.permission.WRITE_CALENDAR")}; - - default: - return {}; + case QApplicationPermission::Contacts: + return {QStringLiteral("android.permission.READ_CONTACTS"), + QStringLiteral("android.permission.WRITE_CONTACTS")}; + case QApplicationPermission::Storage: + return {QStringLiteral("android.permission.READ_EXTERNAL_STORAGE"), + QStringLiteral("android.permission.WRITE_EXTERNAL_STORAGE")}; + case QApplicationPermission::Calendar: + return {QStringLiteral("android.permission.READ_CALENDAR"), + QStringLiteral("android.permission.WRITE_CALENDAR")}; } + + return {}; } /*! @@ -158,7 +158,8 @@ static void sendRequestPermissionsResult(JNIEnv *env, jobject *obj, jint request request->finish(); } -QFuture requestPermissionsInternal(const QStringList &permissions) +QFuture +requestPermissionsInternal(const QStringList &permissions) { QSharedPointer> promise; promise.reset(new QPromise()); @@ -216,43 +217,47 @@ QCoreApplicationPrivate::requestPermission(const QString &permission) return future; } -QFuture groupRequestToSingleResult(const QStringList &permissions) +static bool isBackgroundLocationApi29(QApplicationPermission::PermissionType permission) { - QSharedPointer> promise; - promise.reset(new QPromise()); - QFuture future = promise->future(); - promise->start(); - requestPermissionsInternal(permissions).then( - [promise](QFuture future) { - auto results = future.results(); - if (results.count(QApplicationPermission::Authorized) == results.count()) - promise->addResult(QApplicationPermission::Authorized, 0); - else - promise->addResult(QApplicationPermission::Denied, 0); - promise->finish(); - }); - - return future; + return QNativeInterface::QAndroidApplication::sdkVersion() >= 29 + && (permission == QApplicationPermission::BackgroundLocation + || permission == QApplicationPermission::PreciseBackgroundLocation); } QFuture QCoreApplicationPrivate::requestPermission(QApplicationPermission::PermissionType permission) { + QSharedPointer> promise; + promise.reset(new QPromise()); + QFuture future = promise->future(); + promise->start(); const auto nativePermissions = nativeStringsFromPermission(permission); - if (nativePermissions.size() > 0) - return groupRequestToSingleResult(nativePermissions); + if (nativePermissions.size() > 0) { + requestPermissionsInternal(nativePermissions).then( + [promise, permission](QFuture future) { + auto AuthorizedCount = future.results().count(QApplicationPermission::Authorized); + if (AuthorizedCount > 0) { + if (isBackgroundLocationApi29(permission)) + promise->addResult(future.resultAt(0), 0); + else + promise->addResult(QApplicationPermission::Authorized, 0); + } else { + promise->addResult(QApplicationPermission::Denied, 0); + } + promise->finish(); + }); + + return future; + } - QPromise promise; - QFuture future = promise.future(); - promise.start(); #ifndef QT_NO_EXCEPTIONS - promise.setException(std::make_exception_ptr( + promise->setException(std::make_exception_ptr( std::runtime_error(invalidNativePermissionExcept))); #else promise.addResult(QApplicationPermission::Denied); #endif - promise.finish(); + promise->finish(); return future; }