Baseflow / Baseflow/flutter-permission-handler

Feature Request: iOS Provisional Notification Permissions

Open
#988 4 comments 5 reactions 0 assignees View on GitHub
P2 platform: ios refactor type: enhancement
Dominant language
Dart
Stars
2.2k
Forks
970
Avg merge
14h 22m
Merged PRs (30d)
2

Description

## 🚀 Feature Requests

* Add support for distinguishing the iOS `provisional` notification permission for checking current permission level & requesting full permission

### Contextualize the feature

In iOS 12, [UNAuthorizationStatusProvisional](https://developer.apple.com/documentation/usernotifications/unauthorizationstatus/unauthorizationstatusprovisional?language=objc) was added as a case to [UNAuthorizationStatus](https://developer.apple.com/documentation/usernotifications/unauthorizationstatus?language=objc). This allows a developer to request notification permissions in a way that are initially approved without the user being prompted on a trial basis, but with the restriction that users are not actively interrupted when a notification is received. It is up to the user to check Notification Center themselves and decide if they want to keep the notifications. Much more background in Apple's article [Asking permission to use notifications](https://developer.apple.com/documentation/usernotifications/asking_permission_to_use_notifications).

Currently, if an application has already been granted provisional notification permissions, retrieving the permission via `permission_handler`'s [NotificationPermissionStrategy](https://github.com/Baseflow/flutter-permission-handler/blob/2e47f05ae9dabee2bc671166301aa948259b39f2/permission_handler_apple/ios/Classes/strategies/NotificationPermissionStrategy.m#L61-L81) `permissionStatus` method will return `PermissionStatusGranted`. This does not reflect the actual permission, which would cause client code to think permission is fully granted. If client code wanted to "upgrade" a user's permission to fully authorized by prompting them to enable this permission, we can't, because [requestPermission:](https://github.com/Baseflow/flutter-permission-handler/blob/2e47f05ae9dabee2bc671166301aa948259b39f2/permission_handler_apple/ios/Classes/strategies/NotificationPermissionStrategy.m#L22-L23) checks the permission status first and thinks it is already granted, showing no prompt. By adding support for provisional access, client code could correctly trigger the OS permission dialog when explicit `authorized` access is desired.

If there is a downside to adding this, it's that changing the `permission_handler_platform_interface` may be unavoidable to support this additional permission type. It is unclear to me if this could be done straightforwardly without a breaking change / a major version update; adding to the enum would mean that consumers of the api handling `PermissionStatus` in a `switch` statement could potentially require upgrading.

For additional context, There does seem to be precedence for adding a more niche permission as a status to the overall interface, as the [limited](https://github.com/Baseflow/flutter-permission-handler/pull/421) status was added for that unique case (although was not versioned as a breaking change).

### Describe the feature

#### A possible implementation
- [ ] Add `provisional` (`PermissionStatusProvisional`) as a possible `PermissionStatus`. This status would apply to Apple platforms only ("iOS").
- [ ] Add `provisional` handling to the touch points in `permission_handler_platform_interface`: `PermissionStatus`, `PermissionStatusValue`, `statusByValue`
- [ ] Add `isProvisional` to `PermissionStatusGetters`and `FuturePermissionStatusGetters` in [permission_status.dart](https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler_platform_interface/lib/src/permission_status.dart)
- [ ] Assign a `permissionStatus = PermissionStatusProvisional` in [NotificationPermissionStrategy](https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler_apple/ios/Classes/strategies/NotificationPermissionStrategy.m) when `settings.authorizationStatus == UNAuthorizationStatusProvisional` with platform availability checked (iOS 12+)
- [ ] Check for `PermissionStatusProvisional` in [requestPermission:](https://github.com/Baseflow/flutter-permission-handler/blob/2e47f05ae9dabee2bc671166301aa948259b39f2/permission_handler_apple/ios/Classes/strategies/NotificationPermissionStrategy.m#L22-L27) with platform availability (i.e. iOS 12 is `@available()`) and only call the `completionHandler` early if the status is both not denied and not provisional.
- [ ] Add a `isProvisional` helper method in [permission_handler.dart](https://github.com/Baseflow/flutter-permission-handler/blob/2e47f05ae9dabee2bc671166301aa948259b39f2/permission_handler/lib/permission_handler.dart#L50)

#### A nice to have

A further enhancement would be a way to request notification permissions provisionally as well. I think looking at the current API and again using the [photo permission feature PR](https://github.com/Baseflow/flutter-permission-handler/pull/421/files) as an example (specifically how it added `PermissionGroupPhotosAddOnly`), it might make sense to add a new `provisionalNotification` as a `Permission` type so that it could be requested explicitly, but maybe there's a better way to do that. In this scenario, `NotificationPermissionStrategy.m` would also support the provisional attribute of `UNAuthorizationOptions` that are passed to `UNUserNotificationCenter` `requestAuthorizationWithOptions`

#### Scope Limit

This feature request does **not** extend to another new notification permission type, [ephemeral](https://developer.apple.com/documentation/usernotifications/unauthorizationstatus/ephemeral), which was added in iOS 14 for [App Clips](https://developer.apple.com/documentation/app_clips/enabling_notifications_in_app_clips). Just mentioning here in case anyone is searching for that in the future. For now, app clips in Flutter are an [experimental preview](https://docs.flutter.dev/development/platform-integration/ios/ios-app-clip).

### Platforms affected (mark all that apply)
- [x] :iphone: iOS
- [ ] :robot: Android

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.