This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
powersync-app/nymea-app/platformintegration/android/platformpermissionsandroid.cpp

124 lines
6.9 KiB
C++

#include "platformpermissionsandroid.h"
#include <QApplication>
#include <QDebug>
#include <QAndroidIntent>
#include <QOperatingSystemVersion>
#include "logging.h"
NYMEA_LOGGING_CATEGORY(dcPlatformPermissions, "PlatformPermissions")
PlatformPermissionsAndroid * PlatformPermissionsAndroid::s_instance = nullptr;
#define FLAG_ACTIVITY_NEW_TASK 0x10000000
PlatformPermissionsAndroid::PlatformPermissionsAndroid(QObject *parent)
: PlatformPermissions{parent}
{
s_instance = this;
// If the user switches to the settings app and changes permission settings there, we won't get notified
// in any way, so let's just refresh when we become active
connect(qApp, &QApplication::applicationStateChanged, this, [this](Qt::ApplicationState state){
if (state == Qt::ApplicationActive) {
emit bluetoothPermissionChanged();
emit locationPermissionChanged();
emit backgroundLocationPermissionChanged();
emit notificationsPermissionChanged();
}
});
}
void PlatformPermissionsAndroid::requestPermission(PlatformPermissions::Permission permission)
{
if (permissionMap().contains(permission)) {
qCDebug(dcPlatformPermissions()) << "Requesting permissions:" << permissionMap().value(permission);
QtAndroid::requestPermissions({permissionMap().value(permission)}, &permissionResultCallback);
}
}
void PlatformPermissionsAndroid::openPermissionSettings()
{
qCDebug(dcPlatformPermissions()) << "Opening permission dialog.";
QAndroidJniObject packageName = QtAndroid::androidContext().callObjectMethod("getPackageName", "()Ljava/lang/String;");
QString packageUri = "package:" + packageName.toString();
QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", QAndroidJniObject::fromString(packageUri).object());
QAndroidIntent intent = QAndroidIntent("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.handle().callObjectMethod("setData", "(Landroid/net/Uri;)Landroid/content/Intent;", uri.object());
intent.handle().callObjectMethod("addFlags", "(I)Landroid/content/Intent;", FLAG_ACTIVITY_NEW_TASK);
QtAndroid::androidContext().callMethod<void>("startActivity", "(Landroid/content/Intent;)V", intent.handle().object());
}
QHash<PlatformPermissions::Permission, QStringList> PlatformPermissionsAndroid::permissionMap() const
{
QOperatingSystemVersion osVersion = QOperatingSystemVersion::current();
if (osVersion.majorVersion() <= 9) {
return {
{PlatformPermissions::PermissionBluetooth, {"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION"}}
};
}
if (osVersion.majorVersion() <= 10) {
return {
{PlatformPermissions::PermissionBluetooth, {"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_BACKGROUND_LOCATION"}}
};
}
if (osVersion.majorVersion() <= 12) {
return {
// TODO: Once QtBluetooth does not request the COARSE_LOCATION and FINE_LOCATION for Bluetooth any more, remove it from here. The new Bluetooth permissions would be enough.
{PlatformPermissions::PermissionBluetooth, {"android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_CONNECT", "android.permission.BLUETOOTH_ADVERTISE", "android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_BACKGROUND_LOCATION"}}
};
}
return {
// TODO: Once QtBluetooth does not request the COARSE_LOCATION and FINE_LOCATION for Bluetooth any more, remove it from here. The new Bluetooth permissions would be enough.
{PlatformPermissions::PermissionBluetooth, {"android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_CONNECT", "android.permission.BLUETOOTH_ADVERTISE", "android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_BACKGROUND_LOCATION"}},
{PlatformPermissions::PermissionNotifications, {"android.permission.POST_NOTIFICATIONS"}}
};
}
PlatformPermissions::PermissionStatus PlatformPermissionsAndroid::checkPermission(Permission permission) const
{
PermissionStatus status = PermissionStatusGranted;
QStringList androidPermissions = permissionMap().value(permission);
qCDebug(dcPlatformPermissions()) << "Checking permission" << permission << "(" << androidPermissions << ")";
foreach (const QString androidPermission, androidPermissions) {
if (QtAndroid::shouldShowRequestPermissionRationale(androidPermission) || m_requestedButDeniedPermissions.contains(androidPermission)) {
qCDebug(dcPlatformPermissions()) << "Permission:" << androidPermission << "denied";
status = PermissionStatusDenied;
}
if (QtAndroid::checkPermission(androidPermission) == QtAndroid::PermissionResult::Denied) {
qDebug(dcPlatformPermissions()) << "Permission:" << androidPermission << "not determined";
if (status != PermissionStatusDenied) {
status = PermissionStatusNotDetermined;
}
} else {
qDebug(dcPlatformPermissions()) << "Permission:" << androidPermission << "granted";
}
}
qCDebug(dcPlatformPermissions()) << "Permission status for:" << permission << ":" << status;
return status;
}
void PlatformPermissionsAndroid::permissionResultCallback(const QtAndroid::PermissionResultMap &results)
{
foreach (const QString &androidPermission, results.keys()) {
qCDebug(dcPlatformPermissions()) << "Permission result callback:" << androidPermission << (results.value(androidPermission) == QtAndroid::PermissionResult::Granted ? "Granted" : "Denied");
if (results.value(androidPermission) == QtAndroid::PermissionResult::Denied) {
s_instance->m_requestedButDeniedPermissions.append(androidPermission);
}
}
emit s_instance->bluetoothPermissionChanged();
emit s_instance->locationPermissionChanged();
emit s_instance->backgroundLocationPermissionChanged();
emit s_instance->notificationsPermissionChanged();
}