From 4f1ea207c0211fa7ae1bed71627c9e1015b5eeac Mon Sep 17 00:00:00 2001 From: Emeric Date: Tue, 16 Jan 2024 20:20:12 +0100 Subject: [PATCH] Work on notification permissions --- assets/ios/Info.plist | 2 +- qml/DeviceProbe.qml | 3 + qml/MobileMenu.qml | 4 +- qml/MobilePermissions.qml | 62 +++++++++++++++---- src/NotificationManager.cpp | 4 +- src/thirdparty/AppUtils/utils_os_ios.mm | 31 +++++++--- src/thirdparty/AppUtils/utils_os_ios_notif.mm | 49 +-------------- 7 files changed, 85 insertions(+), 70 deletions(-) diff --git a/assets/ios/Info.plist b/assets/ios/Info.plist index 0e7ba7a..0df66ab 100644 --- a/assets/ios/Info.plist +++ b/assets/ios/Info.plist @@ -21,7 +21,7 @@ CFBundleSignature ${QMAKE_PKGINFO_TYPEINFO} CFBundleVersion - 01040001 + 01040003 LSRequiresIPhoneOS MinimumOSVersion diff --git a/qml/DeviceProbe.qml b/qml/DeviceProbe.qml index c6ea7f8..fdf404e 100644 --- a/qml/DeviceProbe.qml +++ b/qml/DeviceProbe.qml @@ -23,6 +23,9 @@ Loader { if (typeof clickedDevice === "undefined" || !clickedDevice) return if (!clickedDevice.isProbe) return + // ask notification permission + notificationManager.requestNotificationPermissions() + // set device if (currentDevice !== clickedDevice) currentDevice = clickedDevice if (currentDevice.hasProbesBBQ) currentDevice.startRtCapture(true) diff --git a/qml/MobileMenu.qml b/qml/MobileMenu.qml index 5a1a7dc..3a5b857 100644 --- a/qml/MobileMenu.qml +++ b/qml/MobileMenu.qml @@ -74,7 +74,8 @@ Rectangle { appContent.state === "DeviceBrowser" || appContent.state === "SettingsMqtt" || appContent.state === "Settings" || - appContent.state === "About") + appContent.state === "About" || + appContent.state === "AboutPermissions") MobileMenuItem_horizontal { id: menuMainView @@ -99,6 +100,7 @@ Rectangle { colorContent: Theme.colorTabletmenuContent colorHighlight: Theme.colorTabletmenuHighlight + enabled: (deviceManager.bluetooth && deviceManager.bluetoothPermissions) highlighted: (appContent.state === "DeviceBrowser") onClicked: screenDeviceBrowser.loadScreen() } diff --git a/qml/MobilePermissions.qml b/qml/MobilePermissions.qml index e9a262a..289d9f9 100644 --- a/qml/MobilePermissions.qml +++ b/qml/MobilePermissions.qml @@ -111,7 +111,7 @@ Item { //////// - ListSeparatorPadded { height: 16+1 } + ListSeparatorPadded { height: 16+1; visible: Qt.platform.os === "android"; } //////// @@ -120,6 +120,8 @@ Item { anchors.right: parent.right height: 24 + visible: (Qt.platform.os === "android") + RoundButtonIcon { anchors.left: parent.left anchors.leftMargin: Theme.componentMargin @@ -157,6 +159,8 @@ Item { anchors.right: parent.right anchors.rightMargin: Theme.componentMargin + visible: (Qt.platform.os === "android") + text: qsTr("Theengs can activate your device's Bluetooth in order to operate.") textFormat: Text.PlainText wrapMode: Text.WordWrap @@ -191,7 +195,8 @@ Item { onClicked: { utilsApp.vibrate(25) - utilsApp.getMobileBluetoothPermission() + if (Qt.platform.os === "ios") deviceManager.requestBluetoothPermissions() + else utilsApp.getMobileBluetoothPermission() refreshPermissions.start() } } @@ -218,7 +223,7 @@ Item { anchors.right: parent.right anchors.rightMargin: 12 - text: qsTr("The Android operating system requires permission to scan for nearby Bluetooth Low Energy sensors.") + text: qsTr("Permission is required to scan for nearby Bluetooth Low Energy sensors.") textFormat: Text.StyledText wrapMode: Text.WordWrap color: Theme.colorSubText @@ -227,14 +232,16 @@ Item { //////// - ListSeparatorPadded { height: 16+1 } + ListSeparatorPadded { height: 16+1; visible: Qt.platform.os === "android"; } //////// Item { // Location - height: 24 anchors.left: parent.left anchors.right: parent.right + height: 24 + + visible: (Qt.platform.os === "android") RoundButtonIcon { width: 32 @@ -279,6 +286,8 @@ Item { anchors.right: parent.right anchors.rightMargin: 12 + visible: (Qt.platform.os === "android") + text: qsTr("The Android operating system requires applications to ask for device location permission in order to scan for nearby Bluetooth Low Energy sensors.") + "
" + qsTr("Theengs doesn't use, store nor communicate your location to anyone or anything.") textFormat: Text.StyledText @@ -287,9 +296,11 @@ Item { font.pixelSize: Theme.fontSizeContentSmall } ButtonWireframeIcon { - height: 36 anchors.left: parent.left anchors.leftMargin: appHeader.headerPosition + height: 36 + + visible: (Qt.platform.os === "android") primaryColor: Theme.colorPrimary secondaryColor: Theme.colorBackground @@ -311,6 +322,8 @@ Item { anchors.left: parent.left anchors.right: parent.right + visible: (Qt.platform.os === "android") + RoundButtonIcon { width: 32 height: 32 @@ -353,6 +366,8 @@ Item { anchors.right: parent.right anchors.rightMargin: Theme.componentMargin + visible: (Qt.platform.os === "android") + text: qsTr("Some Android devices also require the GPS to be turned on for Bluetooth operations.") textFormat: Text.PlainText wrapMode: Text.WordWrap @@ -361,9 +376,11 @@ Item { } ButtonWireframeIcon { - height: 36 anchors.left: parent.left anchors.leftMargin: appHeader.headerPosition + height: 36 + + visible: (Qt.platform.os === "android") primaryColor: Theme.colorPrimary secondaryColor: Theme.colorBackground @@ -377,7 +394,7 @@ Item { //////// - ListSeparatorPadded { height: 16+1 } + ListSeparatorPadded { height: 16+1; visible: Qt.platform.os === "android"; } //////// @@ -386,6 +403,8 @@ Item { anchors.left: parent.left anchors.right: parent.right + visible: (Qt.platform.os === "android") + RoundButtonIcon { width: 32 height: 32 @@ -429,6 +448,8 @@ Item { anchors.right: parent.right anchors.rightMargin: 12 + visible: (Qt.platform.os === "android") + text: qsTr("Similarly, background location permission is needed if you want to automatically get data from the sensors, while the application is not explicitly opened.") textFormat: Text.StyledText wrapMode: Text.WordWrap @@ -447,7 +468,7 @@ Item { anchors.left: parent.left anchors.right: parent.right - visible: (utilsApp.getAndroidSdkVersion() >= 13) + visible: (Qt.platform.os === "ios" || utilsApp.getAndroidSdkVersion() >= 13) RoundButtonIcon { width: 32 @@ -492,9 +513,9 @@ Item { anchors.right: parent.right anchors.rightMargin: 12 - visible: (utilsApp.getAndroidSdkVersion() >= 13) + visible: (Qt.platform.os === "ios" || utilsApp.getAndroidSdkVersion() >= 13) - text: qsTr("The Android operating system requires permission to send notifications.") + text: qsTr("Permission is required to send notifications.") textFormat: Text.StyledText wrapMode: Text.WordWrap color: Theme.colorSubText @@ -547,6 +568,23 @@ Item { anchors.right: parent.right anchors.rightMargin: Theme.componentMargin + visible: (Qt.platform.os === "ios") + + text: qsTr("If it has no effect, you may have previously refused a permission.") + "
" + + qsTr("You can go to the iOS \"settings\" panel to change a permission manually.") + textFormat: Text.StyledText + wrapMode: Text.WordWrap + color: Theme.colorSubText + font.pixelSize: Theme.fontSizeContentSmall + } + Text { + anchors.left: parent.left + anchors.leftMargin: appHeader.headerPosition + anchors.right: parent.right + anchors.rightMargin: Theme.componentMargin + + visible: (Qt.platform.os === "android") + text: qsTr("If it has no effect, you may have previously refused a permission and clicked on \"don't ask again\".") + "
" + qsTr("You can go to the Android \"application info\" panel to change a permission manually.") textFormat: Text.StyledText @@ -560,6 +598,8 @@ Item { anchors.leftMargin: appHeader.headerPosition height: 36 + visible: (Qt.platform.os === "android") + primaryColor: Theme.colorPrimary secondaryColor: Theme.colorBackground diff --git a/src/NotificationManager.cpp b/src/NotificationManager.cpp index eb40ff2..585ff6b 100644 --- a/src/NotificationManager.cpp +++ b/src/NotificationManager.cpp @@ -23,6 +23,8 @@ #include "utils_os_android.h" #include #include +#elif defined(Q_OS_IOS) +#include "utils_os_ios.h" #endif /* ************************************************************************** */ @@ -41,7 +43,7 @@ NotificationManager *NotificationManager::getInstance() NotificationManager::NotificationManager() { - checkNotificationPermissions(); + //checkNotificationPermissions(); #if defined(Q_OS_ANDROID) connect(this, SIGNAL(notificationChanged()), this, SLOT(updateNotificationAndroid())); diff --git a/src/thirdparty/AppUtils/utils_os_ios.mm b/src/thirdparty/AppUtils/utils_os_ios.mm index 4d16233..f7cf642 100644 --- a/src/thirdparty/AppUtils/utils_os_ios.mm +++ b/src/thirdparty/AppUtils/utils_os_ios.mm @@ -32,43 +32,54 @@ bool UtilsIOS::checkPermission_notification() { - bool status = false; + __block BOOL status = false; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; + UNAuthorizationOptions options = (UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound); + [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *settings) { switch (settings.authorizationStatus) { case UNAuthorizationStatusAuthorized: - NSLog(@"Notifications are allowed"); + //NSLog(@"Notifications are allowed"); + status = true; break; case UNAuthorizationStatusDenied: - NSLog(@"Notifications are denied"); + //NSLog(@"Notifications are denied"); break; case UNAuthorizationStatusNotDetermined: - NSLog(@"Notification permissions not determined yet"); + //NSLog(@"Notification permissions not determined yet"); break; case UNAuthorizationStatusProvisional: - NSLog(@"Provisional authorization granted"); + //NSLog(@"Provisional authorization granted"); + status = true; break; default: - NSLog(@"Unknown notification authorization status"); + //NSLog(@"Unknown notification authorization status"); break; } + + dispatch_semaphore_signal(semaphore); }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + return status; } bool UtilsIOS::getPermission_notification() { - bool status = false; + __block bool status = false; UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) - completionHandler:^(BOOL granted, NSError *_Nullable error) - { + UNAuthorizationOptions options = (UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound); + + [center requestAuthorizationWithOptions:options + completionHandler:^(BOOL granted, NSError *_Nullable error) { if (granted) { NSLog(@"Notification permission granted"); + status = true; } if (error) diff --git a/src/thirdparty/AppUtils/utils_os_ios_notif.mm b/src/thirdparty/AppUtils/utils_os_ios_notif.mm index bad2bff..8065965 100755 --- a/src/thirdparty/AppUtils/utils_os_ios_notif.mm +++ b/src/thirdparty/AppUtils/utils_os_ios_notif.mm @@ -21,6 +21,7 @@ */ #include "utils_os_ios_notif.h" +#include "utils_os_ios.h" #if defined(Q_OS_IOS) @@ -80,56 +81,12 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center bool UtilsIOSNotifications::checkPermission_notification() { - bool status = false; - - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *settings) { - switch (settings.authorizationStatus) { - case UNAuthorizationStatusAuthorized: - NSLog(@"Notifications are allowed"); - break; - case UNAuthorizationStatusDenied: - NSLog(@"Notifications are denied"); - break; - case UNAuthorizationStatusNotDetermined: - NSLog(@"Notification permissions not determined yet"); - break; - case UNAuthorizationStatusProvisional: - NSLog(@"Provisional authorization granted"); - break; - default: - NSLog(@"Unknown notification authorization status"); - break; - } - }]; - - return status; + return UtilsIOS::checkPermission_notification(); } bool UtilsIOSNotifications::getPermission_notification() { - bool status = false; - - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) - completionHandler:^(BOOL granted, NSError *_Nullable error) - { - if (granted) - { - NSLog(@"Notification permission granted"); - } - - if (error) - { - NSLog(@"Local Notification setup failed"); - } - else - { - [[UIApplication sharedApplication] registerForRemoteNotifications]; - } - }]; - - return status; + return UtilsIOS::getPermission_notification(); } bool UtilsIOSNotifications::notify(const QString &title, const QString &message, const int channel)