7#include <QtCore/qstringlist.h>
8#include <QtCore/qfuture.h>
9#include <QtCore/qhash.h>
11#include "private/qandroidextras_p.h"
15using namespace Qt::StringLiterals;
19 QStringList nativeLocationPermissionList;
20 const int sdkVersion = QtAndroidPrivate::androidSdkVersion();
21 static QString backgroundLocation = u"android.permission.ACCESS_BACKGROUND_LOCATION"_s;
22 static QString fineLocation = u"android.permission.ACCESS_FINE_LOCATION"_s;
23 static QString coarseLocation = u"android.permission.ACCESS_COARSE_LOCATION"_s;
30 if (permission.accuracy() == QLocationPermission::Approximate) {
31 nativeLocationPermissionList << coarseLocation;
33 nativeLocationPermissionList << fineLocation;
38 nativeLocationPermissionList << coarseLocation;
47 nativeLocationPermissionList.prepend(backgroundLocation);
49 return nativeLocationPermissionList;
58 static QString bluetoothGeneral = u"android.permission.BLUETOOTH"_s;
59 static QString fineLocation = u"android.permission.ACCESS_FINE_LOCATION"_s;
61 static QString bluetoothScan = u"android.permission.BLUETOOTH_SCAN"_s;
62 static QString bluetoothAdvertise = u"android.permission.BLUETOOTH_ADVERTISE"_s;
63 static QString bluetoothConnect = u"android.permission.BLUETOOTH_CONNECT"_s;
65 if (QtAndroidPrivate::androidSdkVersion() < 31) {
66 return {bluetoothGeneral, fineLocation};
68 const auto modes = permission.communicationModes();
69 QStringList permissionList;
70 if (modes & QBluetoothPermission::Advertise)
71 permissionList << bluetoothAdvertise;
72 if (modes & QBluetoothPermission::Access)
73 permissionList << bluetoothScan << bluetoothConnect;
74 return permissionList;
80 const auto id = permission.type().id();
81 if (id == qMetaTypeId<QLocationPermission>()) {
82 return nativeLocationPermission(*permission.value<QLocationPermission>());
83 }
else if (id == qMetaTypeId<QCameraPermission>()) {
84 return { u"android.permission.CAMERA"_s };
85 }
else if (id == qMetaTypeId<QMicrophonePermission>()) {
86 return { u"android.permission.RECORD_AUDIO"_s };
88 return nativeBluetoothPermission(*permission.value<QBluetoothPermission>());
89 }
else if (id == qMetaTypeId<QContactsPermission>()) {
90 const auto readContactsString = u"android.permission.READ_CONTACTS"_s;
91 switch (permission.value<QContactsPermission>()->accessMode()) {
92 case QContactsPermission::AccessMode::ReadOnly:
93 return { readContactsString };
94 case QContactsPermission::AccessMode::ReadWrite:
95 return { readContactsString, u"android.permission.WRITE_CONTACTS"_s };
97 Q_UNREACHABLE_RETURN({});
98 }
else if (id == qMetaTypeId<QCalendarPermission>()) {
99 const auto readContactsString = u"android.permission.READ_CALENDAR"_s;
100 switch (permission.value<QCalendarPermission>()->accessMode()) {
101 case QCalendarPermission::AccessMode::ReadOnly:
102 return { readContactsString };
103 case QCalendarPermission::AccessMode::ReadWrite:
104 return { readContactsString, u"android.permission.WRITE_CALENDAR"_s };
106 Q_UNREACHABLE_RETURN({});
116 case QtAndroidPrivate::PermissionResult::Authorized:
return Qt::PermissionStatus::Granted;
117 case QtAndroidPrivate::PermissionResult::Denied:
return Qt::PermissionStatus::Denied;
118 default:
return Qt::PermissionStatus::Undetermined;
122using PermissionStatusHash = QHash<
int, Qt::PermissionStatus>;
124 { qMetaTypeId<QCameraPermission>(), Qt::PermissionStatus::Undetermined },
125 { qMetaTypeId<QMicrophonePermission>(), Qt::PermissionStatus::Undetermined },
126 { qMetaTypeId<QBluetoothPermission>(), Qt::PermissionStatus::Undetermined },
127 { qMetaTypeId<QContactsPermission>(), Qt::PermissionStatus::Undetermined },
128 { qMetaTypeId<QCalendarPermission>(), Qt::PermissionStatus::Undetermined },
129 { qMetaTypeId<QLocationPermission>(), Qt::PermissionStatus::Undetermined }
136 for (
const auto &result : androidResults) {
137 const auto status = permissionStatusForAndroidResult(result);
138 if (status == Qt::PermissionStatus::Denied)
141 return Qt::PermissionStatus::Granted;
148 const auto nativePermissionList = nativeStringsFromPermission(permission);
149 if (nativePermissionList.isEmpty())
150 return Qt::PermissionStatus::Granted;
152 QList<QtAndroidPrivate::PermissionResult> androidResults;
153 androidResults.reserve(nativePermissionList.size());
154 for (
const auto &nativePermission : nativePermissionList)
155 androidResults.push_back(QtAndroidPrivate::checkPermission(nativePermission).result());
157 const auto status = getCombinedStatus(androidResults);
158 const auto it = g_permissionStatusHash->constFind(permission.type().id());
159 const bool foundStatus = (it != g_permissionStatusHash->constEnd());
160 const bool itUndetermined = foundStatus && (*it) == Qt::PermissionStatus::Undetermined;
161 if (status == Qt::PermissionStatus::Denied && itUndetermined)
162 return Qt::PermissionStatus::Undetermined;
167 const QPermissions::Private::PermissionCallback &callback)
169 const auto nativePermissionList = nativeStringsFromPermission(permission);
170 if (nativePermissionList.isEmpty()) {
171 callback(Qt::PermissionStatus::Granted);
175 QtAndroidPrivate::requestPermissions(nativePermissionList).then(qApp,
176 [callback, permission](QFuture<QtAndroidPrivate::PermissionResult> future) {
177 const auto androidResults = future.isValid() ? future.results()
178 : QList{QtAndroidPrivate::Denied};
179 const auto status = getCombinedStatus(androidResults);
180 g_permissionStatusHash->insert(permission.type().id(), status);
Access Bluetooth peripherals.
Access the user's location.
\inmodule QtCore \inheaderfile QPermissions
void requestPermission(const QPermission &permission, const PermissionCallback &callback)
Qt::PermissionStatus checkPermission(const QPermission &permission)
static QStringList nativeBluetoothPermission(const QBluetoothPermission &permission)
static Qt::PermissionStatus permissionStatusForAndroidResult(QtAndroidPrivate::PermissionResult result)
static Qt::PermissionStatus getCombinedStatus(const QList< QtAndroidPrivate::PermissionResult > &androidResults)
static QStringList nativeStringsFromPermission(const QPermission &permission)
static QStringList nativeLocationPermission(const QLocationPermission &permission)
Q_GLOBAL_STATIC_WITH_ARGS(PermissionStatusHash, g_permissionStatusHash,({ { qMetaTypeId< QCameraPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QMicrophonePermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QBluetoothPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QContactsPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QCalendarPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QLocationPermission >(), Qt::PermissionStatus::Undetermined } }))