diff --git a/permission_handler_apple/CHANGELOG.md b/permission_handler_apple/CHANGELOG.md index 8065518a1..0326d8f2f 100644 --- a/permission_handler_apple/CHANGELOG.md +++ b/permission_handler_apple/CHANGELOG.md @@ -1,3 +1,10 @@ +## 9.5.0 + +* Migrates iOS platform communication from MethodChannel to Pigeon. +* Adds Dart platform implementation `PermissionHandlerApple` registered via `dartPluginClass`. +* Removes the legacy iOS MethodChannel handler. +* Increases minimum supported Dart SDK version to 3.3.0 to be compatible with pigeon dependency + ## 9.4.10 * Fixed Info.plist lookup in Package.swift to auto-apply permissions. diff --git a/permission_handler_apple/README.md b/permission_handler_apple/README.md index 22d8adfd2..55fd46063 100644 --- a/permission_handler_apple/README.md +++ b/permission_handler_apple/README.md @@ -10,6 +10,16 @@ Since version 9.1.0 of the [permission_handler](https://pub.dev/packages/permiss More detailed instructions on using the API can be found in the [README.md](../permission_handler/README.md) of the [permission_handler](https://pub.dev/packages/permission_handler) package. +## Development + +iOS platform communication uses [Pigeon](https://pub.dev/packages/pigeon). After changing [`pigeon/permission_handler_apple_api.dart`](pigeon/permission_handler_apple_api.dart), regenerate native and Dart bindings from this package directory: + +```bash +dart run pigeon --input pigeon/permission_handler_apple_api.dart +``` + +Commit the generated files under `lib/src/pigeon/` and `ios/permission_handler_apple/Sources/permission_handler_apple/pigeon/`. + ## Issues Please file any issues, bugs, or feature requests as an issue on our [GitHub](https://github.com/Baseflow/flutter-permission-handler/issues) page. Commercial support is available, you can contact us at . diff --git a/permission_handler_apple/ios/permission_handler_apple.podspec b/permission_handler_apple/ios/permission_handler_apple.podspec index ee0359656..53988515f 100644 --- a/permission_handler_apple/ios/permission_handler_apple.podspec +++ b/permission_handler_apple/ios/permission_handler_apple.podspec @@ -3,7 +3,7 @@ # Pod::Spec.new do |s| s.name = 'permission_handler_apple' - s.version = '9.4.8' + s.version = '9.5.0' s.summary = 'Permission plugin for Flutter.' s.description = <<-DESC Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. diff --git a/permission_handler_apple/ios/permission_handler_apple/Package.swift b/permission_handler_apple/ios/permission_handler_apple/Package.swift index 88170e032..1bbaf322a 100644 --- a/permission_handler_apple/ios/permission_handler_apple/Package.swift +++ b/permission_handler_apple/ios/permission_handler_apple/Package.swift @@ -181,6 +181,7 @@ let package = Package( publicHeadersPath: "include", cSettings: [ .headerSearchPath("."), + .headerSearchPath("pigeon"), .headerSearchPath("strategies"), .headerSearchPath("util"), .headerSearchPath("include/permission_handler_apple"), diff --git a/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerPlugin.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerPlugin.m index cfbad93cb..d0e4eaf6b 100644 --- a/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerPlugin.m +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerPlugin.m @@ -1,9 +1,13 @@ #import "PermissionHandlerPlugin.h" +#import "PermissionHandlerAppleApi.h" +#import "Codec.h" +@interface PermissionHandlerPlugin () +@end @implementation PermissionHandlerPlugin { PermissionManager *_Nonnull _permissionManager; - _Nullable FlutterResult _methodResult; + BOOL _permissionRequestInProgress; } - (instancetype)initWithPermissionManager:(PermissionManager *)permissionManager { @@ -11,55 +15,70 @@ - (instancetype)initWithPermissionManager:(PermissionManager *)permissionManager if (self) { _permissionManager = permissionManager; } - + return self; } -+ (void)registerWithRegistrar:(NSObject *)registrar { - FlutterMethodChannel *channel = [FlutterMethodChannel - methodChannelWithName:@"flutter.baseflow.com/permissions/methods" - binaryMessenger:[registrar messenger]]; ++ (void)registerWithRegistrar:(NSObject *)registrar { PermissionManager *permissionManager = [[PermissionManager alloc] initWithStrategyInstances]; PermissionHandlerPlugin *instance = [[PermissionHandlerPlugin alloc] initWithPermissionManager:permissionManager]; - [registrar addMethodCallDelegate:instance channel:channel]; + SetUpPHPermissionHandlerHostApi([registrar messenger], instance); +} + +#pragma mark - PHPermissionHandlerHostApi + +- (nullable NSNumber *)checkPermissionStatusPermission:(NSInteger)permission + error:(FlutterError *_Nullable *_Nonnull)error { + __block NSNumber *statusResult = nil; + [PermissionManager checkPermissionStatus:(PermissionGroup)permission + result:^(id result) { + statusResult = result; + }]; + return statusResult; } -- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - if ([@"checkPermissionStatus" isEqualToString:call.method]) { - PermissionGroup permission = [Codec decodePermissionGroupFrom:call.arguments]; - [PermissionManager checkPermissionStatus:permission result:result]; - } else if ([@"checkServiceStatus" isEqualToString:call.method]) { - PermissionGroup permission = [Codec decodePermissionGroupFrom:call.arguments]; - [PermissionManager checkServiceStatus:permission result:result]; - } else if ([@"requestPermissions" isEqualToString:call.method]) { - if (_methodResult != nil) { - result([FlutterError errorWithCode:@"ERROR_ALREADY_REQUESTING_PERMISSIONS" message:@"A request for permissions is already running, please wait for it to finish before doing another request (note that you can request multiple permissions at the same time)." details:nil]); - return; - } - - _methodResult = result; - NSArray *permissions = [Codec decodePermissionGroupsFrom:call.arguments]; - - [_permissionManager - requestPermissions:permissions completion:^(NSDictionary *permissionRequestResults) { - if (self->_methodResult != nil) { - self->_methodResult(permissionRequestResults); - } - - self->_methodResult = nil; - } errorHandler:^(NSString *errorCode, NSString *errorDescription) { - self->_methodResult([FlutterError errorWithCode:errorCode message:errorDescription details:nil]); - self->_methodResult = nil; - } -]; - - } else if ([@"shouldShowRequestPermissionRationale" isEqualToString:call.method]) { - result(@false); - } else if ([@"openAppSettings" isEqualToString:call.method]) { - [PermissionManager openAppSettings:result]; - } else { - result(FlutterMethodNotImplemented); +- (void)checkServiceStatusPermission:(NSInteger)permission + completion:(void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion { + [PermissionManager checkServiceStatus:(PermissionGroup)permission + result:^(id result) { + completion(result, nil); + }]; +} + +- (void)requestPermissionsPermissions:(NSArray *)permissions + completion:(void (^)(NSDictionary *_Nullable, + FlutterError *_Nullable))completion { + if (_permissionRequestInProgress) { + completion(nil, [FlutterError + errorWithCode:@"ERROR_ALREADY_REQUESTING_PERMISSIONS" + message:@"A request for permissions is already running, please wait for it to " + @"finish before doing another request (note that you can request " + @"multiple permissions at the same time)." + details:nil]); + return; } + + _permissionRequestInProgress = YES; + NSArray *permissionGroups = [Codec decodePermissionGroupsFrom:permissions]; + + [_permissionManager + requestPermissions:permissionGroups + completion:^(NSDictionary *permissionRequestResults) { + self->_permissionRequestInProgress = NO; + completion(permissionRequestResults, nil); + } + errorHandler:^(NSString *errorCode, NSString *errorDescription) { + self->_permissionRequestInProgress = NO; + completion(nil, [FlutterError errorWithCode:errorCode + message:errorDescription + details:nil]); + }]; +} + +- (void)openAppSettingsWithCompletion:(void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion { + [PermissionManager openAppSettings:^(id result) { + completion(result, nil); + }]; } @end diff --git a/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/pigeon/PermissionHandlerAppleApi.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/pigeon/PermissionHandlerAppleApi.h new file mode 100644 index 000000000..6b6e134c0 --- /dev/null +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/pigeon/PermissionHandlerAppleApi.h @@ -0,0 +1,29 @@ +// Autogenerated from Pigeon (v27.1.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +@import Foundation; + +@protocol FlutterBinaryMessenger; +@protocol FlutterMessageCodec; +@class FlutterError; +@class FlutterStandardTypedData; + +NS_ASSUME_NONNULL_BEGIN + + +/// The codec used by all APIs. +NSObject *PHGetPermissionHandlerAppleApiCodec(void); + +@protocol PHPermissionHandlerHostApi +/// @return `nil` only when `error != nil`. +- (nullable NSNumber *)checkPermissionStatusPermission:(NSInteger)permission error:(FlutterError *_Nullable *_Nonnull)error; +- (void)checkServiceStatusPermission:(NSInteger)permission completion:(void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion; +- (void)requestPermissionsPermissions:(NSArray *)permissions completion:(void (^)(NSDictionary *_Nullable, FlutterError *_Nullable))completion; +- (void)openAppSettingsWithCompletion:(void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion; +@end + +extern void SetUpPHPermissionHandlerHostApi(id binaryMessenger, NSObject *_Nullable api); + +extern void SetUpPHPermissionHandlerHostApiWithSuffix(id binaryMessenger, NSObject *_Nullable api, NSString *messageChannelSuffix); + +NS_ASSUME_NONNULL_END diff --git a/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/pigeon/PermissionHandlerAppleApi.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/pigeon/PermissionHandlerAppleApi.m new file mode 100644 index 000000000..88dc99fb0 --- /dev/null +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/pigeon/PermissionHandlerAppleApi.m @@ -0,0 +1,237 @@ +// Autogenerated from Pigeon (v27.1.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#import "PermissionHandlerAppleApi.h" + +#if TARGET_OS_OSX +@import FlutterMacOS; +#else +@import Flutter; +#endif + +static BOOL __attribute__((unused)) FLTPigeonDeepEquals(id _Nullable a, id _Nullable b) { + if (a == b) { + return YES; + } + if (a == nil) { + return b == [NSNull null]; + } + if (b == nil) { + return a == [NSNull null]; + } + if ([a isKindOfClass:[NSNumber class]] && [b isKindOfClass:[NSNumber class]]) { + return [a isEqual:b] || (isnan([(NSNumber *)a doubleValue]) && isnan([(NSNumber *)b doubleValue])); + } + if ([a isKindOfClass:[NSArray class]] && [b isKindOfClass:[NSArray class]]) { + NSArray *arrayA = (NSArray *)a; + NSArray *arrayB = (NSArray *)b; + if (arrayA.count != arrayB.count) { + return NO; + } + for (NSUInteger i = 0; i < arrayA.count; i++) { + if (!FLTPigeonDeepEquals(arrayA[i], arrayB[i])) { + return NO; + } + } + return YES; + } + if ([a isKindOfClass:[NSDictionary class]] && [b isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictA = (NSDictionary *)a; + NSDictionary *dictB = (NSDictionary *)b; + if (dictA.count != dictB.count) { + return NO; + } + for (id keyA in dictA) { + id valueA = dictA[keyA]; + BOOL found = NO; + for (id keyB in dictB) { + if (FLTPigeonDeepEquals(keyA, keyB)) { + id valueB = dictB[keyB]; + if (FLTPigeonDeepEquals(valueA, valueB)) { + found = YES; + break; + } else { + return NO; + } + } + } + if (!found) { + return NO; + } + } + return YES; + } + return [a isEqual:b]; +} + +static NSUInteger __attribute__((unused)) FLTPigeonDeepHash(id _Nullable value) { + if (value == nil || value == (id)[NSNull null]) { + return 0; + } + if ([value isKindOfClass:[NSNumber class]]) { + NSNumber *n = (NSNumber *)value; + double d = n.doubleValue; + if (isnan(d)) { + // Normalize NaN to a consistent hash. + return (NSUInteger)0x7FF8000000000000; + } + if (d == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + d = 0.0; + } + return @(d).hash; + } + if ([value isKindOfClass:[NSArray class]]) { + NSUInteger result = 1; + for (id item in (NSArray *)value) { + result = result * 31 + FLTPigeonDeepHash(item); + } + return result; + } + if ([value isKindOfClass:[NSDictionary class]]) { + NSUInteger result = 0; + NSDictionary *dict = (NSDictionary *)value; + for (id key in dict) { + result += ((FLTPigeonDeepHash(key) * 31) ^ FLTPigeonDeepHash(dict[key])); + } + return result; + } + return [value hash]; +} + +static NSArray *wrapResult(id result, FlutterError *error) { + if (error) { + return @[ + error.code ?: [NSNull null], error.message ?: [NSNull null], error.details ?: [NSNull null] + ]; + } + return @[ result ?: [NSNull null] ]; +} + +static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { + id result = array[key]; + return (result == [NSNull null]) ? nil : result; +} + +@interface PHPermissionHandlerAppleApiPigeonCodecReader : FlutterStandardReader +@end +@implementation PHPermissionHandlerAppleApiPigeonCodecReader +- (nullable id)readValueOfType:(UInt8)type { + switch (type) { + default: + return [super readValueOfType:type]; + } +} +@end + +@interface PHPermissionHandlerAppleApiPigeonCodecWriter : FlutterStandardWriter +@end +@implementation PHPermissionHandlerAppleApiPigeonCodecWriter +- (void)writeValue:(id)value { + { + [super writeValue:value]; + } +} +@end + +@interface PHPermissionHandlerAppleApiPigeonCodecReaderWriter : FlutterStandardReaderWriter +@end +@implementation PHPermissionHandlerAppleApiPigeonCodecReaderWriter +- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { + return [[PHPermissionHandlerAppleApiPigeonCodecWriter alloc] initWithData:data]; +} +- (FlutterStandardReader *)readerWithData:(NSData *)data { + return [[PHPermissionHandlerAppleApiPigeonCodecReader alloc] initWithData:data]; +} +@end + +NSObject *PHGetPermissionHandlerAppleApiCodec(void) { + static FlutterStandardMessageCodec *sSharedObject = nil; + static dispatch_once_t sPred = 0; + dispatch_once(&sPred, ^{ + PHPermissionHandlerAppleApiPigeonCodecReaderWriter *readerWriter = [[PHPermissionHandlerAppleApiPigeonCodecReaderWriter alloc] init]; + sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; + }); + return sSharedObject; +} +void SetUpPHPermissionHandlerHostApi(id binaryMessenger, NSObject *api) { + SetUpPHPermissionHandlerHostApiWithSuffix(binaryMessenger, api, @""); +} + +void SetUpPHPermissionHandlerHostApiWithSuffix(id binaryMessenger, NSObject *api, NSString *messageChannelSuffix) { + messageChannelSuffix = messageChannelSuffix.length > 0 ? [NSString stringWithFormat: @".%@", messageChannelSuffix] : @""; + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.permission_handler_apple.PermissionHandlerHostApi.checkPermissionStatus", messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:PHGetPermissionHandlerAppleApiCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(checkPermissionStatusPermission:error:)], @"PHPermissionHandlerHostApi api (%@) doesn't respond to @selector(checkPermissionStatusPermission:error:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSInteger arg_permission = [GetNullableObjectAtIndex(args, 0) integerValue]; + FlutterError *error; + NSNumber *output = [api checkPermissionStatusPermission:arg_permission error:&error]; + callback(wrapResult(output, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.permission_handler_apple.PermissionHandlerHostApi.checkServiceStatus", messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:PHGetPermissionHandlerAppleApiCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(checkServiceStatusPermission:completion:)], @"PHPermissionHandlerHostApi api (%@) doesn't respond to @selector(checkServiceStatusPermission:completion:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSInteger arg_permission = [GetNullableObjectAtIndex(args, 0) integerValue]; + [api checkServiceStatusPermission:arg_permission completion:^(NSNumber *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.permission_handler_apple.PermissionHandlerHostApi.requestPermissions", messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:PHGetPermissionHandlerAppleApiCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(requestPermissionsPermissions:completion:)], @"PHPermissionHandlerHostApi api (%@) doesn't respond to @selector(requestPermissionsPermissions:completion:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSArray *arg_permissions = GetNullableObjectAtIndex(args, 0); + [api requestPermissionsPermissions:arg_permissions completion:^(NSDictionary *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.permission_handler_apple.PermissionHandlerHostApi.openAppSettings", messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:PHGetPermissionHandlerAppleApiCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(openAppSettingsWithCompletion:)], @"PHPermissionHandlerHostApi api (%@) doesn't respond to @selector(openAppSettingsWithCompletion:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + [api openAppSettingsWithCompletion:^(NSNumber *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } +} diff --git a/permission_handler_apple/lib/permission_handler_apple.dart b/permission_handler_apple/lib/permission_handler_apple.dart new file mode 100644 index 000000000..b85399527 --- /dev/null +++ b/permission_handler_apple/lib/permission_handler_apple.dart @@ -0,0 +1,56 @@ +import 'package:flutter/foundation.dart'; +import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; + +import 'src/pigeon/permission_handler_apple_api.g.dart'; + +/// iOS implementation of [PermissionHandlerPlatform] using Pigeon. +class PermissionHandlerApple extends PermissionHandlerPlatform { + /// Constructs a [PermissionHandlerApple]. + PermissionHandlerApple({PermissionHandlerHostApi? hostApi}) + : _hostApi = hostApi ?? PermissionHandlerHostApi(); + + final PermissionHandlerHostApi _hostApi; + + /// Registers the iOS plugin implementation. + static void registerWith() { + PermissionHandlerPlatform.instance = PermissionHandlerApple(); + } + + @override + Future checkPermissionStatus(Permission permission) async { + final status = await _hostApi.checkPermissionStatus(permission.value); + return PermissionStatusValue.statusByValue(status); + } + + @override + Future checkServiceStatus(Permission permission) async { + final status = await _hostApi.checkServiceStatus(permission.value); + return ServiceStatusValue.statusByValue(status); + } + + @override + Future> requestPermissions( + List permissions, + ) async { + final data = permissions.map((it) => it.value).toList(); + final status = await _hostApi.requestPermissions(data); + return status.map( + (key, value) => MapEntry( + Permission.byValue(key!), + PermissionStatusValue.statusByValue(value!), + ), + ); + } + + @override + Future openAppSettings() async { + return _hostApi.openAppSettings(); + } + + @override + Future shouldShowRequestPermissionRationale( + Permission permission, + ) async { + return SynchronousFuture(false); + } +} diff --git a/permission_handler_apple/lib/src/pigeon/permission_handler_apple_api.g.dart b/permission_handler_apple/lib/src/pigeon/permission_handler_apple_api.g.dart new file mode 100644 index 000000000..fd2ba0ca2 --- /dev/null +++ b/permission_handler_apple/lib/src/pigeon/permission_handler_apple_api.g.dart @@ -0,0 +1,151 @@ +// Autogenerated from Pigeon (v27.1.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List; + +import 'package:flutter/services.dart'; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; + +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; +} + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + default: + return super.readValueOfType(type, buffer); + } + } +} + +class PermissionHandlerHostApi { + /// Constructor for [PermissionHandlerHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + PermissionHandlerHostApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + Future checkPermissionStatus(int permission) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.permission_handler_apple.PermissionHandlerHostApi.checkPermissionStatus$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([permission]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as int; + } + + Future checkServiceStatus(int permission) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.permission_handler_apple.PermissionHandlerHostApi.checkServiceStatus$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([permission]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as int; + } + + Future> requestPermissions(List permissions) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.permission_handler_apple.PermissionHandlerHostApi.requestPermissions$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([permissions]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map).cast(); + } + + Future openAppSettings() async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.permission_handler_apple.PermissionHandlerHostApi.openAppSettings$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as bool; + } +} diff --git a/permission_handler_apple/pigeon/permission_handler_apple_api.dart b/permission_handler_apple/pigeon/permission_handler_apple_api.dart new file mode 100644 index 000000000..c3a52b785 --- /dev/null +++ b/permission_handler_apple/pigeon/permission_handler_apple_api.dart @@ -0,0 +1,27 @@ +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartPackageName: 'permission_handler_apple', + dartOut: 'lib/src/pigeon/permission_handler_apple_api.g.dart', + dartOptions: DartOptions(), + objcHeaderOut: + 'ios/permission_handler_apple/Sources/permission_handler_apple/pigeon/PermissionHandlerAppleApi.h', + objcSourceOut: + 'ios/permission_handler_apple/Sources/permission_handler_apple/pigeon/PermissionHandlerAppleApi.m', + objcOptions: ObjcOptions(prefix: 'PH'), + ), +) +@HostApi() +abstract class PermissionHandlerHostApi { + int checkPermissionStatus(int permission); + + @async + int checkServiceStatus(int permission); + + @async + Map requestPermissions(List permissions); + + @async + bool openAppSettings(); +} diff --git a/permission_handler_apple/pubspec.yaml b/permission_handler_apple/pubspec.yaml index 97963c0ea..23492cb5e 100644 --- a/permission_handler_apple/pubspec.yaml +++ b/permission_handler_apple/pubspec.yaml @@ -2,10 +2,10 @@ 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.4.10 +version: 9.5.0 environment: - sdk: ">=2.18.0 <4.0.0" + sdk: ">=3.3.0 <4.0.0" flutter: ">=3.3.0" flutter: @@ -14,6 +14,7 @@ flutter: platforms: ios: pluginClass: PermissionHandlerPlugin + dartPluginClass: PermissionHandlerApple dependencies: flutter: @@ -22,4 +23,5 @@ dependencies: dev_dependencies: flutter_lints: ^1.0.4 + pigeon: ^27.1.0 plugin_platform_interface: ^2.0.0