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)