summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2021-07-22 14:34:38 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2021-07-26 14:19:17 +0200
commit5604f633c06585246ba473b209c35db67d68740c (patch)
tree5ad2fb41afc78e76bb1c2b9f700e58933d8bba19 /src
parentc89a9ccbccdd7d6ceec669e7effec5786eb3f642 (diff)
Move Android implementation of permissions API to QtAndroidPrivate
And remove plumbing from public QCoreApplication API, which is going to be removed in follow up patch after leaf modules have moved to the private Android API. The public permissions API will be reintroduced in 6.3 after further work. Pick-to: 6.2 Change-Id: I46772284b98d0ced8d4a624a850adaa4a1dfe645 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/CMakeLists.txt1
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp2
-rw-r--r--src/corelib/kernel/qcoreapplication_android.cpp300
-rw-r--r--src/corelib/platform/android/qandroidextras.cpp252
-rw-r--r--src/corelib/platform/android/qandroidextras_p.h40
5 files changed, 292 insertions, 303 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 2df53a0a00..d44011f6c3 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -981,7 +981,6 @@ qt_internal_extend_target(Core CONDITION UNIX AND NOT APPLE
qt_internal_extend_target(Core CONDITION ANDROID AND NOT ANDROID_EMBEDDED
SOURCES
io/qstandardpaths_android.cpp
- kernel/qcoreapplication_android.cpp
io/qstorageinfo_unix.cpp
kernel/qjnienvironment.cpp kernel/qjnienvironment.h
kernel/qjniobject.cpp kernel/qjniobject.h
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 8f53790cb7..10dbe2f684 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -3084,7 +3084,6 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
\sa Q_OBJECT, QObject::tr()
*/
#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
-#if !defined(Q_OS_ANDROID)
QFuture<QApplicationPermission::PermissionResult> defaultPermissionFuture()
{
@@ -3127,7 +3126,6 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
Q_UNUSED(permission)
return defaultPermissionFuture();
}
-#endif
/*!
Requests the \a permission and returns a QFuture representing the
diff --git a/src/corelib/kernel/qcoreapplication_android.cpp b/src/corelib/kernel/qcoreapplication_android.cpp
deleted file mode 100644
index 671db805e3..0000000000
--- a/src/corelib/kernel/qcoreapplication_android.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qcoreapplication.h"
-#include "qcoreapplication_p.h"
-
-#include <QtCore/private/qjnihelpers_p.h>
-#include <QtCore/qfuture.h>
-#include <QtCore/qjnienvironment.h>
-#include <QtCore/qjniobject.h>
-#include <QtCore/qlist.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qpromise.h>
-#include <QtCore/qscopedpointer.h>
-
-QT_BEGIN_NAMESPACE
-
-static const char qtNativeClassName[] = "org/qtproject/qt/android/QtNative";
-
-QApplicationPermission::PermissionResult resultFromAndroid(jint value)
-{
- return value == 0 ? QApplicationPermission::Authorized : QApplicationPermission::Denied;
-}
-
-using PendingPermissionRequestsHash
- = QHash<int, QSharedPointer<QPromise<QApplicationPermission::PermissionResult>>>;
-Q_GLOBAL_STATIC(PendingPermissionRequestsHash, g_pendingPermissionRequests);
-static QBasicMutex g_pendingPermissionRequestsMutex;
-
-static int nextRequestCode()
-{
- static QBasicAtomicInt counter = Q_BASIC_ATOMIC_INITIALIZER(0);
- return counter.fetchAndAddRelaxed(1);
-}
-
-static QStringList nativeStringsFromPermission(QApplicationPermission::PermissionType permission)
-{
- static const auto precisePerm = QStringLiteral("android.permission.ACCESS_FINE_LOCATION");
- static const auto coarsePerm = QStringLiteral("android.permission.ACCESS_COARSE_LOCATION");
- static const auto backgroundPerm =
- QStringLiteral("android.permission.ACCESS_BACKGROUND_LOCATION");
-
- switch (permission) {
- case QApplicationPermission::Location:
- return {coarsePerm};
- case QApplicationPermission::PreciseLocation:
- return {precisePerm};
- 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};
- case QApplicationPermission::Camera:
- 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::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 {};
-}
-
-/*!
- \internal
-
- This function is called when the result of the permission request is available.
- Once a permission is requested, the result is braodcast by the OS and listened
- to by QtActivity which passes it to C++ through a native JNI method call.
- */
-static void sendRequestPermissionsResult(JNIEnv *env, jobject *obj, jint requestCode,
- jobjectArray permissions, jintArray grantResults)
-{
- Q_UNUSED(obj);
-
- QMutexLocker locker(&g_pendingPermissionRequestsMutex);
- auto it = g_pendingPermissionRequests->constFind(requestCode);
- if (it == g_pendingPermissionRequests->constEnd()) {
- qWarning() << "Found no valid pending permission request for request code" << requestCode;
- return;
- }
-
- auto request = *it;
- g_pendingPermissionRequests->erase(it);
- locker.unlock();
-
- const int size = env->GetArrayLength(permissions);
- std::unique_ptr<jint[]> results(new jint[size]);
- env->GetIntArrayRegion(grantResults, 0, size, results.get());
-
- for (int i = 0 ; i < size; ++i) {
- QApplicationPermission::PermissionResult result = resultFromAndroid(results[i]);
- request->addResult(result, i);
- }
-
- request->finish();
-}
-
-QFuture<QApplicationPermission::PermissionResult>
-requestPermissionsInternal(const QStringList &permissions)
-{
- QSharedPointer<QPromise<QApplicationPermission::PermissionResult>> promise;
- promise.reset(new QPromise<QApplicationPermission::PermissionResult>());
- QFuture<QApplicationPermission::PermissionResult> future = promise->future();
- promise->start();
-
- // No mechanism to request permission for SDK version below 23, because
- // permissions defined in the manifest are granted at install time.
- if (QtAndroidPrivate::androidSdkVersion() < 23) {
- for (int i = 0; i < permissions.size(); ++i)
- promise->addResult(QCoreApplication::checkPermission(permissions.at(i)).result(), i);
- promise->finish();
- return future;
- }
-
- const int requestCode = nextRequestCode();
- QMutexLocker locker(&g_pendingPermissionRequestsMutex);
- g_pendingPermissionRequests->insert(requestCode, promise);
-
- QNativeInterface::QAndroidApplication::runOnAndroidMainThread([permissions, requestCode] {
- QJniEnvironment env;
- jclass clazz = env.findClass("java/lang/String");
- auto array = env->NewObjectArray(permissions.size(), clazz, nullptr);
- int index = 0;
-
- for (auto &perm : permissions)
- env->SetObjectArrayElement(array, index++, QJniObject::fromString(perm).object());
-
- QJniObject(QtAndroidPrivate::activity()).callMethod<void>("requestPermissions",
- "([Ljava/lang/String;I)V",
- array,
- requestCode);
- env->DeleteLocalRef(array);
- });
-
- return future;
-}
-
-QFuture<QApplicationPermission::PermissionResult>
-QCoreApplicationPrivate::requestPermission(const QString &permission)
-{
- // avoid the uneccessary call and response to an empty permission string
- if (permission.size() > 0)
- return requestPermissionsInternal({permission});
-
- QPromise<QApplicationPermission::PermissionResult> promise;
- QFuture<QApplicationPermission::PermissionResult> future = promise.future();
- promise.start();
- promise.addResult(QApplicationPermission::Denied);
- promise.finish();
- return future;
-}
-
-static bool isBackgroundLocationApi29(QApplicationPermission::PermissionType permission)
-{
- return QNativeInterface::QAndroidApplication::sdkVersion() >= 29
- && (permission == QApplicationPermission::BackgroundLocation
- || permission == QApplicationPermission::PreciseBackgroundLocation);
-}
-
-QFuture<QApplicationPermission::PermissionResult>
-QCoreApplicationPrivate::requestPermission(QApplicationPermission::PermissionType permission)
-{
- QSharedPointer<QPromise<QApplicationPermission::PermissionResult>> promise;
- promise.reset(new QPromise<QApplicationPermission::PermissionResult>());
- QFuture<QApplicationPermission::PermissionResult> future = promise->future();
- promise->start();
- const auto nativePermissions = nativeStringsFromPermission(permission);
-
- if (nativePermissions.size() > 0) {
- requestPermissionsInternal(nativePermissions).then(
- [promise, permission](QFuture<QApplicationPermission::PermissionResult> 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;
- }
-
- promise->addResult(QApplicationPermission::Denied);
- promise->finish();
- return future;
-}
-
-QFuture<QApplicationPermission::PermissionResult>
-QCoreApplicationPrivate::checkPermission(const QString &permission)
-{
- QPromise<QApplicationPermission::PermissionResult> promise;
- QFuture<QApplicationPermission::PermissionResult> future = promise.future();
- promise.start();
-
- if (permission.size() > 0) {
- auto res = QJniObject::callStaticMethod<jint>(qtNativeClassName,
- "checkSelfPermission",
- "(Ljava/lang/String;)I",
- QJniObject::fromString(permission).object());
- promise.addResult(resultFromAndroid(res));
- } else {
- promise.addResult(QApplicationPermission::Denied);
- }
-
- promise.finish();
- return future;
-}
-
-QFuture<QApplicationPermission::PermissionResult>
-QCoreApplicationPrivate::checkPermission(QApplicationPermission::PermissionType permission)
-{
- const auto nativePermissions = nativeStringsFromPermission(permission);
-
- if (nativePermissions.size() > 0)
- return checkPermission(nativePermissions.first());
-
- QPromise<QApplicationPermission::PermissionResult> promise;
- QFuture<QApplicationPermission::PermissionResult> future = promise.future();
- promise.start();
- promise.addResult(QApplicationPermission::Denied);
- promise.finish();
- return future;
-}
-
-bool QtAndroidPrivate::registerPermissionNatives()
-{
- if (QtAndroidPrivate::androidSdkVersion() < 23)
- return true;
-
- JNINativeMethod methods[] = {
- {"sendRequestPermissionsResult", "(I[Ljava/lang/String;[I)V",
- reinterpret_cast<void *>(sendRequestPermissionsResult)
- }};
-
- QJniEnvironment env;
- return env.registerNativeMethods(qtNativeClassName, methods, 1);
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/platform/android/qandroidextras.cpp b/src/corelib/platform/android/qandroidextras.cpp
index 6d79e6c1e9..e43800e27c 100644
--- a/src/corelib/platform/android/qandroidextras.cpp
+++ b/src/corelib/platform/android/qandroidextras.cpp
@@ -47,6 +47,10 @@
#include <QtCore/qtimer.h>
#include <QtCore/qset.h>
+#if QT_CONFIG(future)
+#include <QtCore/qpromise.h>
+#endif
+
QT_BEGIN_NAMESPACE
class QAndroidParcelPrivate
@@ -1031,4 +1035,252 @@ void QAndroidActivityCallbackResultReceiver::registerCallback(
callbackMap.insert(receiverRequestCode, callbackFunc);
}
+// Permissions API
+
+static const char qtNativeClassName[] = "org/qtproject/qt/android/QtNative";
+
+QtAndroidPrivate::PermissionResult resultFromAndroid(jint value)
+{
+ return value == 0 ? QtAndroidPrivate::Authorized : QtAndroidPrivate::Denied;
+}
+
+using PendingPermissionRequestsHash
+ = QHash<int, QSharedPointer<QPromise<QtAndroidPrivate::PermissionResult>>>;
+Q_GLOBAL_STATIC(PendingPermissionRequestsHash, g_pendingPermissionRequests);
+static QBasicMutex g_pendingPermissionRequestsMutex;
+
+static int nextRequestCode()
+{
+ static QBasicAtomicInt counter = Q_BASIC_ATOMIC_INITIALIZER(0);
+ return counter.fetchAndAddRelaxed(1);
+}
+
+static QStringList nativeStringsFromPermission(QtAndroidPrivate::PermissionType permission)
+{
+ static const auto precisePerm = QStringLiteral("android.permission.ACCESS_FINE_LOCATION");
+ static const auto coarsePerm = QStringLiteral("android.permission.ACCESS_COARSE_LOCATION");
+ static const auto backgroundPerm =
+ QStringLiteral("android.permission.ACCESS_BACKGROUND_LOCATION");
+
+ switch (permission) {
+ case QtAndroidPrivate::Location:
+ return {coarsePerm};
+ case QtAndroidPrivate::PreciseLocation:
+ return {precisePerm};
+ case QtAndroidPrivate::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 QtAndroidPrivate::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};
+ case QtAndroidPrivate::Camera:
+ return {QStringLiteral("android.permission.CAMERA")};
+ case QtAndroidPrivate::Microphone:
+ return {QStringLiteral("android.permission.RECORD_AUDIO")};
+ case QtAndroidPrivate::Bluetooth:
+ return { QStringLiteral("android.permission.BLUETOOTH") };
+ case QtAndroidPrivate::BodySensors:
+ return {QStringLiteral("android.permission.BODY_SENSORS")};
+ case QtAndroidPrivate::PhysicalActivity:
+ return {QStringLiteral("android.permission.ACTIVITY_RECOGNITION")};
+ case QtAndroidPrivate::Contacts:
+ return {QStringLiteral("android.permission.READ_CONTACTS"),
+ QStringLiteral("android.permission.WRITE_CONTACTS")};
+ case QtAndroidPrivate::Storage:
+ return {QStringLiteral("android.permission.READ_EXTERNAL_STORAGE"),
+ QStringLiteral("android.permission.WRITE_EXTERNAL_STORAGE")};
+ case QtAndroidPrivate::Calendar:
+ return {QStringLiteral("android.permission.READ_CALENDAR"),
+ QStringLiteral("android.permission.WRITE_CALENDAR")};
+ }
+
+ return {};
+}
+
+/*!
+ \internal
+
+ This function is called when the result of the permission request is available.
+ Once a permission is requested, the result is braodcast by the OS and listened
+ to by QtActivity which passes it to C++ through a native JNI method call.
+ */
+static void sendRequestPermissionsResult(JNIEnv *env, jobject *obj, jint requestCode,
+ jobjectArray permissions, jintArray grantResults)
+{
+ Q_UNUSED(obj);
+
+ QMutexLocker locker(&g_pendingPermissionRequestsMutex);
+ auto it = g_pendingPermissionRequests->constFind(requestCode);
+ if (it == g_pendingPermissionRequests->constEnd()) {
+ qWarning() << "Found no valid pending permission request for request code" << requestCode;
+ return;
+ }
+
+ auto request = *it;
+ g_pendingPermissionRequests->erase(it);
+ locker.unlock();
+
+ const int size = env->GetArrayLength(permissions);
+ std::unique_ptr<jint[]> results(new jint[size]);
+ env->GetIntArrayRegion(grantResults, 0, size, results.get());
+
+ for (int i = 0 ; i < size; ++i) {
+ QtAndroidPrivate::PermissionResult result = resultFromAndroid(results[i]);
+ request->addResult(result, i);
+ }
+
+ request->finish();
+}
+
+QFuture<QtAndroidPrivate::PermissionResult>
+requestPermissionsInternal(const QStringList &permissions)
+{
+ QSharedPointer<QPromise<QtAndroidPrivate::PermissionResult>> promise;
+ promise.reset(new QPromise<QtAndroidPrivate::PermissionResult>());
+ QFuture<QtAndroidPrivate::PermissionResult> future = promise->future();
+ promise->start();
+
+ // No mechanism to request permission for SDK version below 23, because
+ // permissions defined in the manifest are granted at install time.
+ if (QtAndroidPrivate::androidSdkVersion() < 23) {
+ for (int i = 0; i < permissions.size(); ++i)
+ promise->addResult(QtAndroidPrivate::checkPermission(permissions.at(i)).result(), i);
+ promise->finish();
+ return future;
+ }
+
+ const int requestCode = nextRequestCode();
+ QMutexLocker locker(&g_pendingPermissionRequestsMutex);
+ g_pendingPermissionRequests->insert(requestCode, promise);
+
+ QNativeInterface::QAndroidApplication::runOnAndroidMainThread([permissions, requestCode] {
+ QJniEnvironment env;
+ jclass clazz = env.findClass("java/lang/String");
+ auto array = env->NewObjectArray(permissions.size(), clazz, nullptr);
+ int index = 0;
+
+ for (auto &perm : permissions)
+ env->SetObjectArrayElement(array, index++, QJniObject::fromString(perm).object());
+
+ QJniObject(QtAndroidPrivate::activity()).callMethod<void>("requestPermissions",
+ "([Ljava/lang/String;I)V",
+ array,
+ requestCode);
+ env->DeleteLocalRef(array);
+ });
+
+ return future;
+}
+
+QFuture<QtAndroidPrivate::PermissionResult>
+QtAndroidPrivate::requestPermission(const QString &permission)
+{
+ // avoid the uneccessary call and response to an empty permission string
+ if (permission.size() > 0)
+ return requestPermissionsInternal({permission});
+
+ QPromise<QtAndroidPrivate::PermissionResult> promise;
+ QFuture<QtAndroidPrivate::PermissionResult> future = promise.future();
+ promise.start();
+ promise.addResult(QtAndroidPrivate::Denied);
+ promise.finish();
+ return future;
+}
+
+static bool isBackgroundLocationApi29(QtAndroidPrivate::PermissionType permission)
+{
+ return QNativeInterface::QAndroidApplication::sdkVersion() >= 29
+ && (permission == QtAndroidPrivate::BackgroundLocation
+ || permission == QtAndroidPrivate::PreciseBackgroundLocation);
+}
+
+QFuture<QtAndroidPrivate::PermissionResult>
+QtAndroidPrivate::requestPermission(QtAndroidPrivate::PermissionType permission)
+{
+ QSharedPointer<QPromise<QtAndroidPrivate::PermissionResult>> promise;
+ promise.reset(new QPromise<QtAndroidPrivate::PermissionResult>());
+ QFuture<QtAndroidPrivate::PermissionResult> future = promise->future();
+ promise->start();
+ const auto nativePermissions = nativeStringsFromPermission(permission);
+
+ if (nativePermissions.size() > 0) {
+ requestPermissionsInternal(nativePermissions).then(
+ [promise, permission](QFuture<QtAndroidPrivate::PermissionResult> future) {
+ auto AuthorizedCount = future.results().count(QtAndroidPrivate::Authorized);
+ if (AuthorizedCount > 0) {
+ if (isBackgroundLocationApi29(permission))
+ promise->addResult(future.resultAt(0), 0);
+ else
+ promise->addResult(QtAndroidPrivate::Authorized, 0);
+ } else {
+ promise->addResult(QtAndroidPrivate::Denied, 0);
+ }
+ promise->finish();
+ });
+
+ return future;
+ }
+
+ promise->addResult(QtAndroidPrivate::Denied);
+ promise->finish();
+ return future;
+}
+
+QFuture<QtAndroidPrivate::PermissionResult>
+QtAndroidPrivate::checkPermission(const QString &permission)
+{
+ QPromise<QtAndroidPrivate::PermissionResult> promise;
+ QFuture<QtAndroidPrivate::PermissionResult> future = promise.future();
+ promise.start();
+
+ if (permission.size() > 0) {
+ auto res = QJniObject::callStaticMethod<jint>(qtNativeClassName,
+ "checkSelfPermission",
+ "(Ljava/lang/String;)I",
+ QJniObject::fromString(permission).object());
+ promise.addResult(resultFromAndroid(res));
+ } else {
+ promise.addResult(QtAndroidPrivate::Denied);
+ }
+
+ promise.finish();
+ return future;
+}
+
+QFuture<QtAndroidPrivate::PermissionResult>
+QtAndroidPrivate::checkPermission(QtAndroidPrivate::PermissionType permission)
+{
+ const auto nativePermissions = nativeStringsFromPermission(permission);
+
+ if (nativePermissions.size() > 0)
+ return checkPermission(nativePermissions.first());
+
+ QPromise<QtAndroidPrivate::PermissionResult> promise;
+ QFuture<QtAndroidPrivate::PermissionResult> future = promise.future();
+ promise.start();
+ promise.addResult(QtAndroidPrivate::Denied);
+ promise.finish();
+ return future;
+}
+
+bool QtAndroidPrivate::registerPermissionNatives()
+{
+ if (QtAndroidPrivate::androidSdkVersion() < 23)
+ return true;
+
+ JNINativeMethod methods[] = {
+ {"sendRequestPermissionsResult", "(I[Ljava/lang/String;[I)V",
+ reinterpret_cast<void *>(sendRequestPermissionsResult)
+ }};
+
+ QJniEnvironment env;
+ return env.registerNativeMethods(qtNativeClassName, methods, 1);
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/platform/android/qandroidextras_p.h b/src/corelib/platform/android/qandroidextras_p.h
index 464c7f8aea..587c8661d6 100644
--- a/src/corelib/platform/android/qandroidextras_p.h
+++ b/src/corelib/platform/android/qandroidextras_p.h
@@ -60,6 +60,10 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qmap.h>
+#if QT_CONFIG(future)
+#include <QtCore/qfuture.h>
+#endif
+
QT_BEGIN_NAMESPACE
class QAndroidParcel;
@@ -255,6 +259,42 @@ namespace QtAndroidPrivate
Q_CORE_EXPORT bool bindService(const QAndroidIntent &serviceIntent,
const QAndroidServiceConnection &serviceConnection,
BindFlags flags = BindFlag::None);
+
+#if QT_CONFIG(future)
+ enum PermissionType {
+ Camera,
+ Microphone,
+ Bluetooth,
+ Location,
+ PreciseLocation,
+ BackgroundLocation,
+ PreciseBackgroundLocation,
+ BodySensors,
+ PhysicalActivity,
+ Contacts,
+ Storage,
+ // TODO: remove after usages in other modules are renamed.
+ WriteStorage,
+ Calendar
+ };
+
+ enum PermissionResult {
+ Undetermined,
+ Authorized,
+ Denied
+ };
+
+ Q_CORE_EXPORT QFuture<QtAndroidPrivate::PermissionResult>
+ requestPermission(QtAndroidPrivate::PermissionType permission);
+ Q_CORE_EXPORT QFuture<QtAndroidPrivate::PermissionResult>
+ requestPermission(const QString &permission);
+
+ Q_CORE_EXPORT QFuture<QtAndroidPrivate::PermissionResult>
+ checkPermission(QtAndroidPrivate::PermissionType permission);
+ Q_CORE_EXPORT QFuture<QtAndroidPrivate::PermissionResult>
+ checkPermission(const QString &permission);
+#endif
+
}
QT_END_NAMESPACE