Commit 6d8d9617 by Jeroen Weener Committed by GitHub

Support iOS 17 calendar permissions (iOS) (#1220)

* - Split iOS calendar permission into write only and full access

* - Fixes + adjust readme and bump versions

* - Adjust Changelog.md

* - Support iOS 17+ calendar permissions

* - Update README.md to reflect iOS 17+ calendar permissions

* - Fix PermissionManager.m issue

* - Fix dependencies

* #1108 Adjusted for calendarReadOnly and calendarFullAccess

* #1108 Remove breaking change annotation from changelog

* Switch calendarReadOnly to calendarWriteOnly

* Update permission_handler/CHANGELOG.md

Co-authored-by: TimHoogstrate <tim566@hotmail.com>

* - Adjusted iOS EventPermissionStrategy.m after review

* Added NSCalendarsFullAccessUsageDescription to apple example .plist and podfile

* Fix deprecated calendar permission logic

* Update EventPermissionStrategy.m

* Separate iOS changes

* Group calendar keys in `Info.plist`

---------

Co-authored-by: milosKarakas <milos.karakas@codebluestudio.com>
Co-authored-by: Miloš Karakaš <34490121+MilosKarakas@users.noreply.github.com>
Co-authored-by: TimHoogstrate <tim566@hotmail.com>
parent 4e0d95f6
## 9.2.0
* Adds the support for `Permission.calendarWriteOnly` and `Permission.calendarFullAccess` permissions which are introduced in iOS 17+.
## 9.1.4
* Adds checking whether Bluetooth service is enabled through `Permission.bluetooth.serviceStatus`.
......
......@@ -47,6 +47,9 @@ post_install do |installer|
## dart: PermissionGroup.calendar
'PERMISSION_EVENTS=1',
## dart: PermissionGroup.calendarFullAccess
'PERMISSION_EVENTS_FULL_ACCESS=1',
## dart: PermissionGroup.reminders
'PERMISSION_REMINDERS=1',
......
......@@ -155,7 +155,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
......
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1430"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
......
......@@ -61,6 +61,8 @@
<!-- Permission options for the `calendar` group -->
<key>NSCalendarsUsageDescription</key>
<string>Calendars</string>
<key>NSCalendarsFullAccessUsageDescription</key>
<string>Calendar full access</string>
<!-- Permission options for the `camera` group -->
<key>NSCameraUsageDescription</key>
......
......@@ -5,15 +5,15 @@
// Created by Razvan Lung on 15/02/2019.
//
// ios: PermissionGroupCalendar
// Info.plist: NSCalendarsUsageDescription
// ios: [PermissionGroupCalendar, PermissionGroupCalendarWriteOnly]
// Info.plist: [NSCalendarsUsageDescription, NSCalendarWriteOnlyAccessUsageDescription]
// dart: PermissionGroup.calendar
#ifndef PERMISSION_EVENTS
#define PERMISSION_EVENTS 0
#endif
// ios: PermissionGroupReminders
// Info.plist: NSRemindersUsageDescription
// Info.plist: NSRemindersFullAccessUsageDescription
// dart: PermissionGroup.reminders
#ifndef PERMISSION_REMINDERS
#define PERMISSION_REMINDERS 0
......@@ -110,6 +110,13 @@
#define PERMISSION_CRITICAL_ALERTS 0
#endif
// ios: PermissionGroupCalendarFullAccess
// Info.plist: [NSCalendarFullAccessUsageDescription]
// dart: PermissionGroup.calendarFullAccess
#ifndef PERMISSION_EVENTS_FULL_ACCESS
#define PERMISSION_EVENTS_FULL_ACCESS 0
#endif
typedef NS_ENUM(int, PermissionGroup) {
PermissionGroupCalendar = 0,
PermissionGroupCamera,
......@@ -146,7 +153,9 @@ typedef NS_ENUM(int, PermissionGroup) {
PermissiongroupVideos,
PermissionGroupAudio,
PermissionGroupScheduleExactAlarm,
PermissionGroupSensorsAlways
PermissionGroupSensorsAlways,
PermissionGroupCalendarWriteOnly,
PermissionGroupCalendarFullAccess
};
typedef NS_ENUM(int, PermissionStatus) {
......
......@@ -98,6 +98,8 @@
+ (id)createPermissionStrategy:(PermissionGroup)permission {
switch (permission) {
case PermissionGroupCalendar:
case PermissionGroupCalendarWriteOnly:
case PermissionGroupCalendarFullAccess:
return [EventPermissionStrategy new];
case PermissionGroupCamera:
return [AudioVideoPermissionStrategy new];
......
......@@ -6,7 +6,7 @@
#import <Foundation/Foundation.h>
#import "PermissionStrategy.h"
#if PERMISSION_EVENTS | PERMISSION_REMINDERS
#if PERMISSION_EVENTS | PERMISSION_EVENTS_FULL_ACCESS | PERMISSION_REMINDERS
#import <EventKit/EventKit.h>
......
......@@ -5,22 +5,12 @@
#import "EventPermissionStrategy.h"
#if PERMISSION_EVENTS | PERMISSION_REMINDERS
#if PERMISSION_EVENTS | PERMISSION_EVENTS_FULL_ACCESS | PERMISSION_REMINDERS
@implementation EventPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
if (permission == PermissionGroupCalendar) {
#if PERMISSION_EVENTS
return [EventPermissionStrategy permissionStatus:EKEntityTypeEvent];
#endif
} else if (permission == PermissionGroupReminders) {
#if PERMISSION_REMINDERS
return [EventPermissionStrategy permissionStatus:EKEntityTypeReminder];
#endif
}
return PermissionStatusDenied;
return [EventPermissionStrategy permissionStatus:permission];
}
- (void)checkServiceStatus:(PermissionGroup)permission completionHandler:(ServiceStatusHandler)completionHandler {
......@@ -34,55 +24,124 @@
completionHandler(permissionStatus);
return;
}
EKEntityType entityType;
if (permission == PermissionGroupCalendar) {
#if PERMISSION_EVENTS
entityType = EKEntityTypeEvent;
#else
if (permission == PermissionGroupCalendar || permission == PermissionGroupCalendarFullAccess) {
if (@available(iOS 17.0, *)) {
#if !PERMISSION_EVENTS_FULL_ACCESS
completionHandler(PermissionStatusDenied);
return;
#endif
} else {
#if !PERMISSION_EVENTS
completionHandler(PermissionStatusDenied);
return;
#endif
}
} else if (permission == PermissionGroupCalendarWriteOnly) {
#if !PERMISSION_EVENTS && !PERMISSION_EVENTS_FULL_ACCESS
completionHandler(PermissionStatusDenied);
return;
#endif
} else if (permission == PermissionGroupReminders) {
#if PERMISSION_REMINDERS
entityType = EKEntityTypeReminder;
#else
#if !PERMISSION_REMINDERS
completionHandler(PermissionStatusDenied);
return;
#endif
} else {
completionHandler(PermissionStatusPermanentlyDenied);
return;
}
EKEventStore *eventStore = [[EKEventStore alloc] init];
[eventStore requestAccessToEntityType:entityType completion:^(BOOL granted, NSError *error) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusPermanentlyDenied);
if (@available(iOS 17.0, *)) {
if (permission == PermissionGroupCalendar || permission == PermissionGroupCalendarFullAccess) {
[eventStore requestFullAccessToEventsWithCompletion:^(BOOL granted, NSError *error) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusPermanentlyDenied);
}
}];
} else if (permission == PermissionGroupCalendarWriteOnly) {
[eventStore requestWriteOnlyAccessToEventsWithCompletion:^(BOOL granted, NSError *error) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusPermanentlyDenied);
}
}];
} else if (permission == PermissionGroupReminders) {
[eventStore requestFullAccessToRemindersWithCompletion:^(BOOL granted, NSError *error) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusPermanentlyDenied);
}
}];
}
}];
} else {
EKEntityType entityType = [EventPermissionStrategy getEntityType:permission];
[eventStore requestAccessToEntityType:entityType completion:^(BOOL granted, NSError *error) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusPermanentlyDenied);
}
}];
}
}
+ (PermissionStatus)permissionStatus:(EKEntityType)entityType {
+ (PermissionStatus)permissionStatus:(PermissionGroup)permission {
EKEntityType entityType = [EventPermissionStrategy getEntityType:permission];
EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:entityType];
switch (status) {
case EKAuthorizationStatusNotDetermined:
return PermissionStatusDenied;
case EKAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case EKAuthorizationStatusDenied:
return PermissionStatusPermanentlyDenied;
case EKAuthorizationStatusAuthorized:
return PermissionStatusGranted;
if (@available(iOS 17.0, *)) {
switch (status) {
case EKAuthorizationStatusNotDetermined:
return PermissionStatusDenied;
case EKAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case EKAuthorizationStatusDenied:
return PermissionStatusPermanentlyDenied;
case EKAuthorizationStatusFullAccess:
return PermissionStatusGranted;
case EKAuthorizationStatusWriteOnly:
if (permission == PermissionGroupCalendarWriteOnly) {
return PermissionStatusGranted;
}
return PermissionStatusDenied;
}
} else {
switch (status) {
case EKAuthorizationStatusNotDetermined:
return PermissionStatusDenied;
case EKAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case EKAuthorizationStatusDenied:
return PermissionStatusPermanentlyDenied;
case EKAuthorizationStatusAuthorized:
return PermissionStatusGranted;
case EKAuthorizationStatusWriteOnly:
//not available on iOS 16 and below
break;
}
}
return PermissionStatusDenied;
}
+ (EKEntityType)getEntityType:(PermissionGroup)permission {
if (permission == PermissionGroupCalendar || permission == PermissionGroupCalendarFullAccess || permission == PermissionGroupCalendarWriteOnly) {
return EKEntityTypeEvent;
} else if (permission == PermissionGroupReminders) {
return EKEntityTypeReminder;
}
return nil;
}
@end
#else
......
......@@ -2,7 +2,7 @@ name: permission_handler_apple
description: Permission plugin for Flutter. This plugin provides the iOS API to request and check permissions.
repository: https://github.com/baseflow/flutter-permission-handler
issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues
version: 9.1.4
version: 9.2.0
environment:
sdk: ">=2.15.0 <4.0.0"
......@@ -18,7 +18,7 @@ flutter:
dependencies:
flutter:
sdk: flutter
permission_handler_platform_interface: ^3.11.2
permission_handler_platform_interface: ^4.0.0
dev_dependencies:
flutter_lints: ^1.0.4
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment