From 6db0842e9ffdab58e42761fadc4678ad8abd72d6 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Thu, 19 Dec 2024 18:36:44 -0500 Subject: [PATCH 1/2] add ios.forceRegister option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On iOS, notification permissions only control *user-facing* notifications. Silent/invisible notifications can be received and handled in the background even when the user denies notification permissions. When forceRegister is true, registerForRemoteNotifications will be called on init even if requestAuthorizationWithOptions comes back with granted=FALSE. | `ios.forceRegister` | `boolean` | `false` | Optional. If `true` the app will register for remote notifications, even if the user has denied notification permissions. On iOS, notification permissions only control *user-facing* notifications – background pushes can still be received. | --- docs/API.md | 1 + src/ios/PushPlugin.m | 6 ++++-- src/ios/PushPluginSettings.h | 1 + src/ios/PushPluginSettings.m | 5 +++++ types/index.d.ts | 6 ++++++ 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/API.md b/docs/API.md index 5d85be2fa..34d878695 100644 --- a/docs/API.md +++ b/docs/API.md @@ -127,6 +127,7 @@ All iOS boolean options can also be specified as `string` | `ios.categories` | `Object` | `{}` | Optional. The data required in order to enable Action Buttons for iOS. See [Action Buttons on iOS](https://github.com/phonegap/phonegap-plugin-push/blob/master/docs/PAYLOAD.md#action-buttons-1) for more details. | | `ios.critical` | `boolean` | `false` | Optional. If `true` the device can show up critical alerts. (Possible since iOS 12 with a special entitlement) **Note:** the value you set this option to the first time you call the init method will be how the application always acts. Once this is set programmatically in the init method it can only be changed manually by the user in Settings > Notifications > `App Name`. This is normal iOS behaviour. | | `ios.forceShow` | `boolean` | `false` | Optional. Controls the behavior of the notification when app is in foreground. If `true` and app is in foreground, it will show a notification in the notification drawer, the same way as when the app is in background (and `on('notification')` callback will be called _only when the user clicks the notification_). When `false` and app is in foreground, the `on('notification')` callback will be called immediately. | +| `ios.forceRegister` | `boolean` | `false` | Optional. If `true` the app will register for remote notifications, even if the user has denied notification permissions. On iOS, notification permissions only control *user-facing* notifications – background pushes can still be received. | #### iOS GCM support diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index 3d25f23f4..03030ea0c 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -41,6 +41,7 @@ @interface PushPlugin () @property (nonatomic, assign) BOOL isInline; @property (nonatomic, assign) BOOL clearBadge; @property (nonatomic, assign) BOOL forceShow; +@property (nonatomic, assign) BOOL forceRegister; @property (nonatomic, assign) BOOL coldstart; @property (nonatomic, copy) void (^backgroundTaskcompletionHandler)(UIBackgroundFetchResult); @@ -164,6 +165,7 @@ - (void)init:(CDVInvokedUrlCommand *)command { self.isInline = NO; self.forceShow = [settings forceShowEnabled]; self.clearBadge = [settings clearBadgeEnabled]; + self.forceRegister = [settings forceRegisterEnabled]; if (self.clearBadge) { dispatch_async(dispatch_get_main_queue(), ^{ [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; @@ -749,7 +751,7 @@ - (void)handleNotificationSettingsWithAuthorizationOptions:(NSNumber *)authoriza NSLog(@"[PushPlugin] Error during authorization request: %@", error.localizedDescription); } - if (granted) { + if (granted || self.forceRegister) { NSLog(@"[PushPlugin] Notification permissions granted."); dispatch_async(dispatch_get_main_queue(), ^{ [[UIApplication sharedApplication] registerForRemoteNotifications]; @@ -787,7 +789,7 @@ - (void)handleNotificationSettingsWithAuthorizationOptions:(NSNumber *)authoriza NSLog(@"[PushPlugin] Error during authorization request: %@", error.localizedDescription); } - if (granted) { + if (granted || self.forceRegister) { NSLog(@"[PushPlugin] New notification permissions granted."); dispatch_async(dispatch_get_main_queue(), ^{ [[UIApplication sharedApplication] registerForRemoteNotifications]; diff --git a/src/ios/PushPluginSettings.h b/src/ios/PushPluginSettings.h index 0ac12cff1..dec59b57f 100644 --- a/src/ios/PushPluginSettings.h +++ b/src/ios/PushPluginSettings.h @@ -16,6 +16,7 @@ @property (nonatomic, readonly) BOOL criticalEnabled; @property (nonatomic, readonly) BOOL clearBadgeEnabled; @property (nonatomic, readonly) BOOL forceShowEnabled; +@property (nonatomic, readonly) BOOL forceRegisterEnabled; @property (nonatomic, readonly) BOOL voipEnabled; @property (nonatomic, readonly, strong) NSArray *fcmTopics; diff --git a/src/ios/PushPluginSettings.m b/src/ios/PushPluginSettings.m index 037ddc9f9..24b766f8f 100644 --- a/src/ios/PushPluginSettings.m +++ b/src/ios/PushPluginSettings.m @@ -34,6 +34,7 @@ - (instancetype)initWithDefaults { @"critical" : @(NO), @"clearBadge" : @(NO), @"forceShow" : @(NO), + @"forceRegister" : @(NO), @"voip" : @(NO), @"fcmTopics" : @[], @"categories" : [NSSet set] @@ -164,6 +165,10 @@ - (BOOL)forceShowEnabled { return [self.settingsDictionary[@"forceShow"] boolValue]; } +- (BOOL)forceRegisterEnabled { + return [self.settingsDictionary[@"forceRegister"] boolValue]; +} + - (BOOL)voipEnabled { return [self.settingsDictionary[@"voip"] boolValue]; } diff --git a/types/index.d.ts b/types/index.d.ts index 77e150b71..ad0719fed 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -244,6 +244,12 @@ declare namespace PhonegapPluginPush { * If true will always show a notification, even when the app is on the foreground. Default is false. */ forceShow?: boolean + /** + * If true the app will register for remote notifications, even if the user has denied notification permissions. + * On iOS, notification permissions only control user-facing notifications – background pushes can still be received. + * Default is false. + */ + forceRegister?: boolean } } From be5efaddaaa7fa8673fd6fc6b0cb253093ed8e6d Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Fri, 20 Dec 2024 00:11:22 -0500 Subject: [PATCH 2/2] docs: update description of ios.forceRegister option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: エリス --- docs/API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/API.md b/docs/API.md index 34d878695..298c96272 100644 --- a/docs/API.md +++ b/docs/API.md @@ -127,7 +127,7 @@ All iOS boolean options can also be specified as `string` | `ios.categories` | `Object` | `{}` | Optional. The data required in order to enable Action Buttons for iOS. See [Action Buttons on iOS](https://github.com/phonegap/phonegap-plugin-push/blob/master/docs/PAYLOAD.md#action-buttons-1) for more details. | | `ios.critical` | `boolean` | `false` | Optional. If `true` the device can show up critical alerts. (Possible since iOS 12 with a special entitlement) **Note:** the value you set this option to the first time you call the init method will be how the application always acts. Once this is set programmatically in the init method it can only be changed manually by the user in Settings > Notifications > `App Name`. This is normal iOS behaviour. | | `ios.forceShow` | `boolean` | `false` | Optional. Controls the behavior of the notification when app is in foreground. If `true` and app is in foreground, it will show a notification in the notification drawer, the same way as when the app is in background (and `on('notification')` callback will be called _only when the user clicks the notification_). When `false` and app is in foreground, the `on('notification')` callback will be called immediately. | -| `ios.forceRegister` | `boolean` | `false` | Optional. If `true` the app will register for remote notifications, even if the user has denied notification permissions. On iOS, notification permissions only control *user-facing* notifications – background pushes can still be received. | +| `ios.forceRegister` | `boolean` | `false` | Optional. If set to true, the app will continue to register an APNs token for remote notifications. Notification permissions only control disruptive user-facing notifications, such as alerts, sounds, badges, and critical notifications. Even if the user denies these permissions, background push notifications can still be received. If the user disables "Background App Refresh", silent push notifications will be blocked. | #### iOS GCM support