From 590063aa195d00431d4467ac62fb002215b1cc59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 4 Dec 2025 21:46:40 +0100 Subject: [PATCH] Fix android permissions --- .../android/platformpermissionsandroid.cpp | 260 ++++++++---------- .../platformpermissions.cpp | 9 +- 2 files changed, 123 insertions(+), 146 deletions(-) diff --git a/nymea-app/platformintegration/android/platformpermissionsandroid.cpp b/nymea-app/platformintegration/android/platformpermissionsandroid.cpp index 1dbdaad7..d8f1e5dd 100644 --- a/nymea-app/platformintegration/android/platformpermissionsandroid.cpp +++ b/nymea-app/platformintegration/android/platformpermissionsandroid.cpp @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include #include @@ -64,15 +66,16 @@ PlatformPermissions::PermissionStatus PlatformPermissionsAndroid::checkPermissio case PlatformPermissions::PermissionBluetooth: { QBluetoothPermission permission; - // Status prüfen - auto status = qApp->checkPermission(permission); + const auto permissionStatus = qApp->checkPermission(permission); - switch (status) { + switch (permissionStatus) { case Qt::PermissionStatus::Granted: qCDebug(dcPlatformPermissions()) << "Bluetooth permission already granted."; + status = PermissionStatusGranted; break; case Qt::PermissionStatus::Denied: qCDebug(dcPlatformPermissions()) << "Bluetooth permission denied."; + status = PermissionStatusDenied; break; case Qt::PermissionStatus::Undetermined: qCDebug(dcPlatformPermissions()) << "Bluetooth permission not yet requested. Requesting..."; @@ -82,32 +85,75 @@ PlatformPermissions::PermissionStatus PlatformPermissionsAndroid::checkPermissio else qCDebug(dcPlatformPermissions()) << "Bluetooth permission denied after request."; }); + status = PermissionStatusNotDetermined; break; } break; } case PlatformPermissions::PermissionLocalNetwork: { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::Android, 13)) { + status = PermissionStatusGranted; + break; + } + + const auto permissionResult = QtAndroidPrivate::checkPermission("android.permission.NEARBY_WIFI_DEVICES").result(); + switch (permissionResult) { + case QtAndroidPrivate::Authorized: + qCDebug(dcPlatformPermissions()) << "Local network permission already granted."; + status = PermissionStatusGranted; + break; + case QtAndroidPrivate::Denied: + qCDebug(dcPlatformPermissions()) << "Local network permission denied."; + status = PermissionStatusDenied; + break; + case QtAndroidPrivate::Undetermined: + qCDebug(dcPlatformPermissions()) << "Local network permission not yet requested."; + status = PermissionStatusNotDetermined; + break; + } + break; + } + case PlatformPermissions::PermissionLocation: { QLocationPermission permission; permission.setAccuracy(QLocationPermission::Precise); - // Status prüfen - auto status = qApp->checkPermission(permission); + const auto permissionStatus = qApp->checkPermission(permission); - switch (status) { + switch (permissionStatus) { case Qt::PermissionStatus::Granted: qCDebug(dcPlatformPermissions()) << "Location permission already granted."; + status = PermissionStatusGranted; break; case Qt::PermissionStatus::Denied: qCDebug(dcPlatformPermissions()) << "Location permission denied."; + status = PermissionStatusDenied; break; case Qt::PermissionStatus::Undetermined: - qCDebug(dcPlatformPermissions()) << "Location permission not yet requested. Requesting..."; - qApp->requestPermission(permission, [](const QPermission &perm){ - if (perm.status() == Qt::PermissionStatus::Granted) - qCDebug(dcPlatformPermissions()) << "Location permission granted after request."; - else - qCDebug(dcPlatformPermissions()) << "Location permission denied after request."; - }); + qCDebug(dcPlatformPermissions()) << "Location permission not yet requested."; + status = PermissionStatusNotDetermined; + break; + } + break; + } + case PlatformPermissions::PermissionBackgroundLocation: { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::Android, 10)) { + // No dedicated background permission; use foreground status instead. + return checkPermission(PermissionLocation); + } + + const auto permissionResult = QtAndroidPrivate::checkPermission("android.permission.ACCESS_BACKGROUND_LOCATION").result(); + switch (permissionResult) { + case QtAndroidPrivate::Authorized: + qCDebug(dcPlatformPermissions()) << "Background location permission already granted."; + status = PermissionStatusGranted; + break; + case QtAndroidPrivate::Denied: + qCDebug(dcPlatformPermissions()) << "Background location permission denied."; + status = PermissionStatusDenied; + break; + case QtAndroidPrivate::Undetermined: + qCDebug(dcPlatformPermissions()) << "Background location permission not yet requested."; + status = PermissionStatusNotDetermined; break; } break; @@ -148,7 +194,7 @@ void PlatformPermissionsAndroid::requestPermission(PlatformPermissions::Permissi switch (platformPermission) { case PlatformPermissions::PermissionBluetooth: qCDebug(dcPlatformPermissions()) << "Requesting bluetooth permission"; - qApp->requestPermission(QLocationPermission{}, [platformPermission](const QPermission &permission) { + qApp->requestPermission(QBluetoothPermission{}, [platformPermission](const QPermission &permission) { if (permission.status() == Qt::PermissionStatus::Denied) { qCWarning(dcPlatformPermissions()) << "Bluetooth permission denied."; s_instance->m_requestedButDeniedPermissions.append(platformPermission); @@ -176,20 +222,49 @@ void PlatformPermissionsAndroid::requestPermission(PlatformPermissions::Permissi }); break; } - case PlatformPermissions::PermissionLocalNetwork: { - QFuture permission_request = QtAndroidPrivate::requestPermission("android.permission.POST_NOTIFICATIONS"); - switch(permission_request.result()) { - case QtAndroidPrivate::Undetermined: - qWarning() << "Permission for posting notifications undetermined!"; - break; - case QtAndroidPrivate::Authorized: - qDebug() << "Permission for posting notifications authorized"; - break; - case QtAndroidPrivate::Denied: - qWarning() << "Permission for posting notifications denied!"; + case PlatformPermissions::PermissionBackgroundLocation: { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::Android, 10)) { + emit s_instance->backgroundLocationPermissionChanged(); break; } + auto permissionRequest = QtAndroidPrivate::requestPermission("android.permission.ACCESS_BACKGROUND_LOCATION"); + permissionRequest.then(qApp, [platformPermission](QtAndroidPrivate::PermissionResult result) { + switch(result) { + case QtAndroidPrivate::Undetermined: + qWarning() << "Permission for background location undetermined!"; + s_instance->m_requestedButDeniedPermissions.append(platformPermission); + break; + case QtAndroidPrivate::Authorized: + qDebug() << "Permission for background location authorized"; + break; + case QtAndroidPrivate::Denied: + qWarning() << "Permission for background location denied!"; + s_instance->m_requestedButDeniedPermissions.append(platformPermission); + break; + } + emit s_instance->backgroundLocationPermissionChanged(); + }); + break; + } + case PlatformPermissions::PermissionLocalNetwork: { + auto permissionRequest = QtAndroidPrivate::requestPermission("android.permission.NEARBY_WIFI_DEVICES"); + permissionRequest.then(qApp, [platformPermission](QtAndroidPrivate::PermissionResult result) { + switch(result) { + case QtAndroidPrivate::Undetermined: + qWarning() << "Permission for local network undetermined!"; + s_instance->m_requestedButDeniedPermissions.append(platformPermission); + break; + case QtAndroidPrivate::Authorized: + qDebug() << "Permission for local network authorized"; + break; + case QtAndroidPrivate::Denied: + qWarning() << "Permission for local network denied!"; + s_instance->m_requestedButDeniedPermissions.append(platformPermission); + break; + } + emit s_instance->localNetworkPermissionChanged(); + }); break; } case PlatformPermissions::PermissionNotifications: { @@ -199,128 +274,27 @@ void PlatformPermissionsAndroid::requestPermission(PlatformPermissions::Permissi break; } - QFuture permission_request = QtAndroidPrivate::requestPermission("android.permission.POST_NOTIFICATIONS"); - auto result = permission_request.result(); - switch(result) { - case QtAndroidPrivate::Undetermined: - qWarning() << "Permission for posting notifications undetermined!"; - s_instance->m_requestedButDeniedPermissions.append(platformPermission); - break; - case QtAndroidPrivate::Authorized: - qDebug() << "Permission for posting notifications authorized"; - break; - case QtAndroidPrivate::Denied: - qWarning() << "Permission for posting notifications denied!"; - s_instance->m_requestedButDeniedPermissions.append(platformPermission); - break; - } - emit s_instance->notificationsPermissionChanged(); + auto permissionRequest = QtAndroidPrivate::requestPermission("android.permission.POST_NOTIFICATIONS"); + permissionRequest.then(qApp, [platformPermission](QtAndroidPrivate::PermissionResult result) { + switch(result) { + case QtAndroidPrivate::Undetermined: + qWarning() << "Permission for posting notifications undetermined!"; + s_instance->m_requestedButDeniedPermissions.append(platformPermission); + break; + case QtAndroidPrivate::Authorized: + qDebug() << "Permission for posting notifications authorized"; + break; + case QtAndroidPrivate::Denied: + qWarning() << "Permission for posting notifications denied!"; + s_instance->m_requestedButDeniedPermissions.append(platformPermission); + break; + } + emit s_instance->notificationsPermissionChanged(); + }); break; } default: qCWarning(dcPlatformPermissions()) << "Requested platform permission" << platformPermission << "but is not implemented yet."; break; } - - emit s_instance->locationPermissionChanged(); - emit s_instance->backgroundLocationPermissionChanged(); - emit s_instance->notificationsPermissionChanged(); - - // if (permissionMap().contains(permission)) { - // qCDebug(dcPlatformPermissions()) << "Requesting permissions:" << permissionMap().value(permission); - - - - // qApp->requestPermission(QCameraPermission{}, [](const QPermission &permission) { - - - // if (permission.status() == Qt::PermissionStatus::Granted) - // takePhoto(); - // }); - - // // QtAndroid::requestPermissions({permissionMap().value(permission)}, &permissionResultCallback); - // } } - -// void PlatformPermissionsAndroid::openPermissionSettings() -// { -// qCDebug(dcPlatformPermissions()) << "Opening permission dialog."; -// QJniObject packageName = QtAndroid::androidContext().callObjectMethod("getPackageName", "()Ljava/lang/String;"); -// QString packageUri = "package:" + packageName.toString(); -// QJniObject uri = QJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", QJniObject::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("startActivity", "(Landroid/content/Intent;)V", intent.handle().object()); -// } - -// QHash 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(); -// } diff --git a/nymea-app/platformintegration/platformpermissions.cpp b/nymea-app/platformintegration/platformpermissions.cpp index 246c3b04..178fa914 100644 --- a/nymea-app/platformintegration/platformpermissions.cpp +++ b/nymea-app/platformintegration/platformpermissions.cpp @@ -33,11 +33,14 @@ PlatformPermissions *PlatformPermissions::instance() { #ifdef Q_OS_ANDROID - return new PlatformPermissionsAndroid(); + static PlatformPermissionsAndroid instance; + return &instance; #elif defined Q_OS_IOS - return new PlatformPermissionsIOS(); + static PlatformPermissionsIOS instance; + return &instance; #else - return new PlatformPermissions(); + static PlatformPermissions instance; + return &instance; #endif }