Commit d7b96380 by Razvan Cristian Lung

migrate Swift and Kotlin to ObjC and Java

parent afb1db36
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 06b979c4d5e1b499745422269f01a00341257058
channel: master
project_type: plugin
connection.project.dir=
eclipse.preferences.version=1
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.permissionhandlerexample">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
package com.example.permissionhandlerexample;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.permissionhandlerexample">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
//
// Enums.h
// permission_handler
//
// Created by Razvan Lung on 15/02/2019.
//
typedef NS_ENUM(int, PermissionGroup) {
PermissionGroupCalendar = 0,
PermissionGroupCamera,
PermissionGroupContacts,
PermissionGroupLocation,
PermissionGroupLocationAlways,
PermissionGroupLocationWhenInUse,
PermissionGroupMediaLibrary,
PermissionGroupMicrophone,
PermissionGroupPhone,
PermissionGroupPhotos,
PermissionGroupReminders,
PermissionGroupSensors,
PermissionGroupSms,
PermissionGroupSpeech,
PermissionGroupStorage,
PermissionGroupUnknown,
};
typedef NS_ENUM(int, PermissionStatus) {
PermissionStatusDenied = 0,
PermissionStatusDisabled,
PermissionStatusGranted,
PermissionStatusRestricted,
PermissionStatusUnknown,
};
typedef NS_ENUM(int, ServiceStatus) {
ServiceStatusDisabled = 0,
ServiceStatusEnabled,
ServiceStatusNotApplicable,
ServiceStatusUnknown,
};
//
// PermissionManager.h
// permission_handler
//
// Created by Razvan Lung on 15/02/2019.
//
#import <Flutter/Flutter.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "AudioVideoPermissionStrategy.h"
#import "ContactPermissionStrategy.h"
#import "EventPermissionStrategy.h"
#import "LocationPermissionStrategy.h"
#import "MediaLibraryPermissionStrategy.h"
#import "PermissionStrategy.h"
#import "PhotoPermissionStrategy.h"
#import "SensorPermissionStrategy.h"
#import "SpeechPermissionStrategy.h"
#import "UnknownPermissionStrategy.h"
#import "Enums.h"
#import "Codec.h"
typedef void (^PermissionRequestCompletion)(NSDictionary *permissionRequestResults);
@interface PermissionManager : NSObject
- (instancetype)initWithStrategyInstances;
+ (void)checkPermissionStatus:(enum PermissionGroup)permission result:(FlutterResult)result;
+ (void)checkServiceStatus:(enum PermissionGroup)permission result:(FlutterResult)result;
+ (void)openAppSettings:(FlutterResult)result;
- (void)requestPermissions:(NSArray *)permissions completion:(PermissionRequestCompletion)completion;
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "PermissionManager.h"
@implementation PermissionManager {
NSMutableArray <id <PermissionStrategy>> *_strategyInstances;
}
- (instancetype)initWithStrategyInstances {
self = [super init];
if (self) {
_strategyInstances = _strategyInstances = [[NSMutableArray alloc] init];
}
return self;
}
+ (void)checkPermissionStatus:(enum PermissionGroup)permission result:(FlutterResult)result {
id <PermissionStrategy> permissionStrategy = [PermissionManager createPermissionStrategy:permission];
PermissionStatus status = [permissionStrategy checkPermissionStatus:permission];
result([Codec encodePermissionStatus:status]);
}
+ (void)checkServiceStatus:(enum PermissionGroup)permission result:(FlutterResult)result {
id <PermissionStrategy> permissionStrategy = [PermissionManager createPermissionStrategy:permission];
ServiceStatus status = [permissionStrategy checkServiceStatus:permission];
result([Codec encodeServiceStatus:status]);
}
- (void)requestPermissions:(NSArray *)permissions completion:(PermissionRequestCompletion)completion {
NSMutableSet *requestQueue = [[NSMutableSet alloc] initWithArray:permissions];
NSMutableDictionary *permissionStatusResult = [[NSMutableDictionary alloc] init];
for (int i = 0; i < permissions.count; ++i) {
PermissionGroup value;
[permissions[i] getValue:&value];
PermissionGroup permission = value;
id <PermissionStrategy> permissionStrategy = [PermissionManager createPermissionStrategy:permission];
[_strategyInstances addObject:permissionStrategy];
[permissionStrategy requestPermission:permission completionHandler:^(PermissionStatus permissionStatus) {
permissionStatusResult[@(permission)] = @(permissionStatus);
[requestQueue removeObject:@(permission)];
[self->_strategyInstances removeObject:permissionStrategy];
if (requestQueue.count == 0) {
completion(permissionStatusResult);
return;
}
}];
}
}
+ (void)openAppSettings:(FlutterResult)result {
if (@available(iOS 8.0, *)) {
NSURL *url = [[NSURL alloc] initWithString:UIApplicationOpenSettingsURLString];
if (url == nil) {
result(@false);
return;
}
if (@available(iOS 10, *)) {
if (![UIApplication.sharedApplication canOpenURL:url]) {
result(@false);
return;
}
NSDictionary *optionsKeyDictionary = @{UIApplicationOpenURLOptionUniversalLinksOnly: @true};
[[UIApplication sharedApplication]
openURL:url options:optionsKeyDictionary completionHandler:^(BOOL success) {
result([[NSNumber alloc] initWithBool:success]);
}];
return;
} else {
BOOL success = [[UIApplication sharedApplication] openURL:url];
result([[NSNumber alloc] initWithBool:success]);
}
}
result(@false);
}
+ (id)createPermissionStrategy:(PermissionGroup)permission {
switch (permission) {
case PermissionGroupCalendar:
return [EventPermissionStrategy new];
case PermissionGroupCamera:
return [AudioVideoPermissionStrategy new];
case PermissionGroupContacts:
return [ContactPermissionStrategy new];
case PermissionGroupLocation:
case PermissionGroupLocationAlways:
case PermissionGroupLocationWhenInUse:
return [[LocationPermissionStrategy alloc] initWithLocationManager];
case PermissionGroupMediaLibrary:
return [MediaLibraryPermissionStrategy new];
case PermissionGroupMicrophone:
return [AudioVideoPermissionStrategy new];
case PermissionGroupPhotos:
return [PhotoPermissionStrategy new];
case PermissionGroupReminders:
return [EventPermissionStrategy new];
case PermissionGroupSensors:
return [SensorPermissionStrategy new];
case PermissionGroupSpeech:
return [SpeechPermissionStrategy new];
default:
return [UnknownPermissionStrategy new];
}
}
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <AVFoundation/AVFoundation.h>
#import <Foundation/Foundation.h>
#import "PermissionStrategy.h"
@interface AudioVideoPermissionStrategy : NSObject <PermissionStrategy>
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "AudioVideoPermissionStrategy.h"
@implementation AudioVideoPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
if (permission == PermissionGroupCamera) {
return [AudioVideoPermissionStrategy permissionStatus:AVMediaTypeVideo];
} else if (permission == PermissionGroupMicrophone) {
return [AudioVideoPermissionStrategy permissionStatus:AVMediaTypeAudio];
}
return PermissionStatusUnknown;
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return ServiceStatusNotApplicable;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
PermissionStatus status = [self checkPermissionStatus:permission];
if (status != PermissionStatusUnknown) {
completionHandler(status);
return;
}
AVMediaType mediaType;
if (permission == PermissionGroupCamera) {
mediaType = AVMediaTypeVideo;
} else if (permission == PermissionGroupMicrophone) {
mediaType = AVMediaTypeAudio;
} else {
completionHandler(PermissionStatusUnknown);
return;
}
[AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusDenied);
}
}];
}
+ (PermissionStatus)permissionStatus:(AVMediaType const)mediaType {
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
switch (status) {
case AVAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case AVAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case AVAuthorizationStatusDenied:
return PermissionStatusDenied;
case AVAuthorizationStatusAuthorized:
return PermissionStatusGranted;
}
return PermissionStatusUnknown;
}
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <AddressBook/ABAddressBook.h>
#import <Contacts/Contacts.h>
#import <Foundation/Foundation.h>
#import "PermissionStrategy.h"
@interface ContactPermissionStrategy : NSObject <PermissionStrategy>
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "ContactPermissionStrategy.h"
@implementation ContactPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
return [ContactPermissionStrategy permissionStatus];
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return ServiceStatusNotApplicable;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
PermissionStatus status = [self checkPermissionStatus:permission];
if (status != PermissionStatusUnknown) {
completionHandler(status);
}
if (@available(iOS 9.0, *)) {
[ContactPermissionStrategy requestPermissionsFromContactStore:completionHandler];
} else {
[ContactPermissionStrategy requestPermissionsFromAddressBook:completionHandler];
}
}
+ (PermissionStatus)permissionStatus {
if (@available(iOS 9.0, *)) {
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
switch (status) {
case CNAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case CNAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case CNAuthorizationStatusDenied:
return PermissionStatusDenied;
case CNAuthorizationStatusAuthorized:
return PermissionStatusGranted;
}
} else {
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
switch (status) {
case kABAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case kABAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case kABAuthorizationStatusDenied:
return PermissionStatusDenied;
case kABAuthorizationStatusAuthorized:
return PermissionStatusGranted;
}
}
return PermissionStatusUnknown;
}
+ (void)requestPermissionsFromContactStore:(PermissionStatusHandler)completionHandler API_AVAILABLE(ios(9)) {
CNContactStore *contactStore = [CNContactStore new];
[contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError *__nullable error) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusDenied);
}
}];
ABAddressBookRequestAccessWithCompletion(ABAddressBookCreate(), ^(bool granted, CFErrorRef error) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusDenied);
}
});
}
+ (void)requestPermissionsFromAddressBook:(PermissionStatusHandler)completionHandler {
ABAddressBookRequestAccessWithCompletion(ABAddressBookCreate(), ^(bool granted, CFErrorRef error) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusDenied);
}
});
}
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <EventKit/EventKit.h>
#import "PermissionStrategy.h"
@interface EventPermissionStrategy : NSObject <PermissionStrategy>
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "EventPermissionStrategy.h"
@implementation EventPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
if (permission == PermissionGroupCalendar) {
return [EventPermissionStrategy permissionStatus:EKEntityTypeEvent];
} else if (permission == PermissionGroupReminders) {
return [EventPermissionStrategy permissionStatus:EKEntityTypeReminder];
}
return PermissionStatusUnknown;
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return ServiceStatusNotApplicable;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
PermissionStatus permissionStatus = [self checkPermissionStatus:permission];
if (permissionStatus != PermissionStatusUnknown) {
completionHandler(permissionStatus);
return;
}
EKEntityType entityType;
if (permission == PermissionGroupCalendar) {
entityType = EKEntityTypeEvent;
} else if (permission == PermissionGroupReminders) {
entityType = EKEntityTypeReminder;
} else {
completionHandler(PermissionStatusUnknown);
return;
}
EKEventStore *eventStore = [[EKEventStore alloc] init];
[eventStore requestAccessToEntityType:entityType completion:^(BOOL granted, NSError *error) {
if (granted) {
completionHandler(PermissionStatusGranted);
} else {
completionHandler(PermissionStatusDenied);
}
}];
}
+ (PermissionStatus)permissionStatus:(EKEntityType)entityType {
EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:entityType];
switch (status) {
case EKAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case EKAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case EKAuthorizationStatusDenied:
return PermissionStatusDenied;
case EKAuthorizationStatusAuthorized:
return PermissionStatusGranted;
}
return PermissionStatusUnknown;
}
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>
#import "PermissionStrategy.h"
@interface LocationPermissionStrategy : NSObject <PermissionStrategy, CLLocationManagerDelegate>
- (instancetype)initWithLocationManager;
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "LocationPermissionStrategy.h"
@implementation LocationPermissionStrategy {
CLLocationManager *_locationManager;
PermissionStatusHandler _permissionStatusHandler;
PermissionGroup _requestedPermission;
}
- (instancetype)initWithLocationManager {
self = [super init];
if (self) {
_locationManager = [CLLocationManager new];
_locationManager.delegate = self;
}
return self;
}
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
return [LocationPermissionStrategy permissionStatus:permission];
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return [CLLocationManager locationServicesEnabled] ? ServiceStatusEnabled : ServiceStatusDisabled;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
PermissionStatus status = [self checkPermissionStatus:permission];
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse && permission == PermissionGroupLocationAlways) {
// don't do anything and continue requesting permissions
} else if (status != PermissionStatusUnknown) {
completionHandler(status);
}
_permissionStatusHandler = completionHandler;
_requestedPermission = permission;
if (permission == PermissionGroupLocation) {
if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] != nil) {
[_locationManager requestAlwaysAuthorization];
} else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] != nil) {
[_locationManager requestWhenInUseAuthorization];
} else {
[[NSException exceptionWithName:NSInternalInconsistencyException reason:@"To use location in iOS8 you need to define either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in the app bundle's Info.plist file" userInfo:nil] raise];
}
} else if (permission == PermissionGroupLocationAlways) {
if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] != nil) {
[_locationManager requestAlwaysAuthorization];
} else {
[[NSException exceptionWithName:NSInternalInconsistencyException reason:@"To use location in iOS8 you need to define NSLocationAlwaysUsageDescription in the app bundle's Info.plist file" userInfo:nil] raise];
}
} else if (permission == PermissionGroupLocationWhenInUse) {
if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] != nil) {
[_locationManager requestWhenInUseAuthorization];
} else {
[[NSException exceptionWithName:NSInternalInconsistencyException reason:@"To use location in iOS8 you need to define NSLocationWhenInUseUsageDescription in the app bundle's Info.plist file" userInfo:nil] raise];
}
}
}
// {WARNING}
// This is called when the location manager is first initialized and raises the following situations:
// 1. When we first request [PermissionGroupLocationWhenInUse] and then [PermissionGroupLocationAlways]
// this will be called when the [CLLocationManager] is first initialized with
// [kCLAuthorizationStatusAuthorizedWhenInUse]. As a consequence we send back the result to early.
// 2. When we first request [PermissionGroupLocationWhenInUse] and then [PermissionGroupLocationAlways]
// and the user doesn't allow for [kCLAuthorizationStatusAuthorizedAlways] this method is not called
// at all.
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusNotDetermined) {
return;
}
if (_permissionStatusHandler == nil || @(_requestedPermission) == nil) {
return;
}
PermissionStatus permissionStatus = [LocationPermissionStrategy
determinePermissionStatus:_requestedPermission authorizationStatus:status];
_permissionStatusHandler(permissionStatus);
}
+ (PermissionStatus)permissionStatus:(PermissionGroup)permission {
CLAuthorizationStatus authorizationStatus = [CLLocationManager authorizationStatus];
PermissionStatus status = [LocationPermissionStrategy
determinePermissionStatus:permission authorizationStatus:authorizationStatus];
if ((status == PermissionStatusGranted || status == PermissionStatusDenied)
&& ![CLLocationManager locationServicesEnabled]) {
return PermissionStatusDisabled;
}
return status;
}
+ (PermissionStatus)determinePermissionStatus:(PermissionGroup)permission authorizationStatus:(CLAuthorizationStatus)authorizationStatus {
if (@available(iOS 8.0, *)) {
if (permission == PermissionGroupLocationAlways) {
switch (authorizationStatus) {
case kCLAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case kCLAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case kCLAuthorizationStatusDenied:
case kCLAuthorizationStatusAuthorizedWhenInUse:
return PermissionStatusDenied;
case kCLAuthorizationStatusAuthorizedAlways:
return PermissionStatusGranted;
}
}
switch (authorizationStatus) {
case kCLAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case kCLAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case kCLAuthorizationStatusDenied:
return PermissionStatusDenied;
case kCLAuthorizationStatusAuthorizedAlways:
case kCLAuthorizationStatusAuthorizedWhenInUse:
return PermissionStatusGranted;
}
}
switch (authorizationStatus) {
case kCLAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case kCLAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case kCLAuthorizationStatusDenied:
return PermissionStatusDenied;
case kCLAuthorizationStatusAuthorized:
return PermissionStatusGranted;
default:
return PermissionStatusUnknown;
}
}
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <MediaPlayer/MediaPlayer.h>
#include "PermissionStrategy.h"
@interface MediaLibraryPermissionStrategy : NSObject <PermissionStrategy>
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "MediaLibraryPermissionStrategy.h"
@implementation MediaLibraryPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
return [MediaLibraryPermissionStrategy permissionStatus];
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return ServiceStatusNotApplicable;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
PermissionStatus status = [self checkPermissionStatus:permission];
if (status != PermissionStatusUnknown) {
completionHandler(status);
return;
}
if (@available(iOS 9.3, *)) {
[MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus status) {
completionHandler([MediaLibraryPermissionStrategy determinePermissionStatus:status]);
}];
} else {
completionHandler(PermissionStatusUnknown);
return;
}
}
+ (PermissionStatus)permissionStatus {
if (@available(iOS 9.3, *)) {
MPMediaLibraryAuthorizationStatus status = [MPMediaLibrary authorizationStatus];
return [MediaLibraryPermissionStrategy determinePermissionStatus:status];
}
return PermissionStatusUnknown;
}
+ (PermissionStatus)determinePermissionStatus:(MPMediaLibraryAuthorizationStatus)authorizationStatus {
switch (authorizationStatus) {
case MPMediaLibraryAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case MPMediaLibraryAuthorizationStatusDenied:
return PermissionStatusDenied;
case MPMediaLibraryAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case MPMediaLibraryAuthorizationStatusAuthorized:
return PermissionStatusGranted;
}
return PermissionStatusUnknown;
}
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Enums.h"
typedef void (^PermissionStatusHandler)(PermissionStatus permissionStatus);
@protocol PermissionStrategy <NSObject>
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission;
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission;
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler;
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "PermissionStrategy.h"
#import <Photos/Photos.h>
@interface PhotoPermissionStrategy : NSObject <PermissionStrategy>
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "PhotoPermissionStrategy.h"
@implementation PhotoPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
return [PhotoPermissionStrategy permissionStatus];
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return ServiceStatusNotApplicable;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
PermissionStatus status = [self checkPermissionStatus:permission];
if (status != PermissionStatusUnknown) {
completionHandler(status);
return;
}
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus authorizationStatus) {
completionHandler([PhotoPermissionStrategy determinePermissionStatus:authorizationStatus]);
}];
}
+ (PermissionStatus)permissionStatus {
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
return [PhotoPermissionStrategy determinePermissionStatus:status];
}
+ (PermissionStatus)determinePermissionStatus:(PHAuthorizationStatus)authorizationStatus {
switch (authorizationStatus) {
case PHAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case PHAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case PHAuthorizationStatusDenied:
return PermissionStatusDenied;
case PHAuthorizationStatusAuthorized:
return PermissionStatusGranted;
}
return PermissionStatusUnknown;
}
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <CoreMotion/CoreMotion.h>
#import <Foundation/Foundation.h>
#import "PermissionStrategy.h"
@interface SensorPermissionStrategy : NSObject <PermissionStrategy>
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "SensorPermissionStrategy.h"
@implementation SensorPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
return [SensorPermissionStrategy permissionStatus];
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
if (@available(iOS 11.0, *)) {
return [CMMotionActivityManager isActivityAvailable]
? ServiceStatusEnabled
: ServiceStatusDisabled;
}
return ServiceStatusUnknown;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
PermissionStatus status = [self checkPermissionStatus:permission];
if (status != PermissionStatusUnknown) {
completionHandler(status);
return;
}
if (@available(iOS 11.0, *)) {
CMMotionActivityManager *motionManager = [[CMMotionActivityManager alloc] init];
NSDate *today = [NSDate new];
[motionManager queryActivityStartingFromDate:today toDate:today toQueue:[NSOperationQueue mainQueue] withHandler:^(NSArray<CMMotionActivity *> *__nullable activities, NSError *__nullable error) {
if (error != nil && error.code == CMErrorMotionActivityNotAuthorized) {
completionHandler(PermissionStatusDenied);
} else {
completionHandler(PermissionStatusGranted);
}
}];
} else {
completionHandler(PermissionStatusUnknown);
}
}
+ (PermissionStatus)permissionStatus {
if (@available(iOS 11.0, *)) {
CMAuthorizationStatus status = [CMMotionActivityManager authorizationStatus];
PermissionStatus permissionStatus;
switch (status) {
case CMAuthorizationStatusNotDetermined:
permissionStatus = PermissionStatusUnknown;
break;
case CMAuthorizationStatusRestricted:
permissionStatus = PermissionStatusRestricted;
break;
case CMAuthorizationStatusDenied:
permissionStatus = PermissionStatusDenied;
break;
case CMAuthorizationStatusAuthorized:
permissionStatus = PermissionStatusGranted;
break;
default:
permissionStatus = PermissionStatusGranted;
}
if ((permissionStatus == PermissionStatusGranted || permissionStatus == PermissionStatusDenied) && ![CMMotionActivityManager isActivityAvailable]) {
return PermissionStatusDisabled;
} else {
return permissionStatus;
}
}
return PermissionStatusUnknown;
}
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "PermissionStrategy.h"
#import <Speech/Speech.h>
@interface SpeechPermissionStrategy : NSObject <PermissionStrategy>
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "SpeechPermissionStrategy.h"
@implementation SpeechPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
return [SpeechPermissionStrategy permissionStatus];
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return ServiceStatusNotApplicable;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
PermissionStatus status = [self checkPermissionStatus:permission];
if (status != PermissionStatusUnknown) {
completionHandler(status);
return;
}
if (@available(iOS 10.0, *)) {
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus authorizationStatus) {
completionHandler([SpeechPermissionStrategy determinePermissionStatus:authorizationStatus]);
}];
} else {
completionHandler(PermissionStatusUnknown);
}
}
+ (PermissionStatus)permissionStatus {
if (@available(iOS 10.0, *)) {
SFSpeechRecognizerAuthorizationStatus status = [SFSpeechRecognizer authorizationStatus];
return [SpeechPermissionStrategy determinePermissionStatus:status];
}
return PermissionStatusUnknown;
}
+ (PermissionStatus)determinePermissionStatus:(SFSpeechRecognizerAuthorizationStatus)authorizationStatus {
switch (authorizationStatus) {
case SFSpeechRecognizerAuthorizationStatusNotDetermined:
return PermissionStatusUnknown;
case SFSpeechRecognizerAuthorizationStatusDenied:
return PermissionStatusDenied;
case SFSpeechRecognizerAuthorizationStatusRestricted:
return PermissionStatusRestricted;
case SFSpeechRecognizerAuthorizationStatusAuthorized:
return PermissionStatusGranted;
}
return PermissionStatusUnknown;
}
@end
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "PermissionStrategy.h"
@interface UnknownPermissionStrategy : NSObject <PermissionStrategy>
@end
\ No newline at end of file
//
// Created by Razvan Lung(long1eu) on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "UnknownPermissionStrategy.h"
@implementation UnknownPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
return PermissionStatusUnknown;
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return ServiceStatusUnknown;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
completionHandler(PermissionStatusUnknown);
}
@end
\ No newline at end of file
//
// Created by Razvan Lung on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Enums.h"
@interface Codec : NSObject
+ (PermissionGroup)decodePermissionGroupFrom:(NSNumber *_Nonnull)event;
+ (NSArray*_Nullable)decodePermissionGroupsFrom:(NSArray<NSNumber *> *_Nullable)event;
+ (NSNumber *_Nullable)encodePermissionStatus:(enum PermissionStatus)permissionStatus;
+ (NSNumber *_Nullable)encodeServiceStatus:(enum ServiceStatus)serviceStatus;
@end
//
// Created by Razvan Lung on 2019-02-15.
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
//
#import "Codec.h"
@implementation Codec
+ (PermissionGroup)decodePermissionGroupFrom:(NSNumber *)event {
return (PermissionGroup) event.intValue;
}
+ (NSArray *_Nullable)decodePermissionGroupsFrom:(NSArray<NSNumber *> *)event {
NSMutableArray *result = [[NSMutableArray alloc] init];
for (NSNumber *number in event) {
[result addObject:@([self decodePermissionGroupFrom:number])];
}
return [[NSArray alloc] initWithArray:result];
}
+ (NSNumber *_Nullable)encodePermissionStatus:(enum PermissionStatus)permissionStatus {
return [[NSNumber alloc] initWithInt:permissionStatus];
}
+ (NSNumber *_Nullable)encodeServiceStatus:(enum ServiceStatus)serviceStatus {
return [[NSNumber alloc] initWithInt:serviceStatus];
}
@end
/// Defines the state of a permission group
class PermissionStatus {
const PermissionStatus._(this.value);
final int value;
/// Permission to access the requested feature is denied by the user.
static const PermissionStatus denied = PermissionStatus._(0);
/// The feature is disabled (or not available) on the device.
static const PermissionStatus disabled = PermissionStatus._(1);
/// Permission to access the requested feature is granted by the user.
static const PermissionStatus granted = PermissionStatus._(2);
/// The user granted restricted access to the requested feature (only on iOS).
static const PermissionStatus restricted = PermissionStatus._(3);
/// Permission is in an unknown state
static const PermissionStatus unknown = PermissionStatus._(4);
static const List<PermissionStatus> values = <PermissionStatus>[
denied,
disabled,
granted,
restricted,
unknown,
];
static const List<String> _names = <String>[
'denied',
'disabled',
'granted',
'restricted',
'unknown',
];
@override
String toString() => 'PermissionStatus.${_names[value]}';
}
/// Defines the state of a service related to the permission group
class ServiceStatus {
const ServiceStatus._(this.value);
final int value;
/// The service for the supplied permission group is disabled.
static const ServiceStatus disabled = ServiceStatus._(0);
/// The service for the supplied permission group is enabled.
static const ServiceStatus enable = ServiceStatus._(1);
/// There is no service for the supplied permission group.
static const ServiceStatus notApplicable = ServiceStatus._(2);
/// The unknown service status indicates the state of the service could not be determined.
static const ServiceStatus unknown = ServiceStatus._(3);
static const List<ServiceStatus> values = <ServiceStatus>[
disabled,
enable,
notApplicable,
unknown,
];
static const List<String> _names = <String>[
'disabled',
'enable',
'notApplicable',
'unknown',
];
@override
String toString() => 'ServiceStatus.${_names[value]}';
}
/// Defines the permission groups for which permissions can be checked or requested.
class PermissionGroup {
const PermissionGroup._(this.value);
final int value;
/// Android: Calendar
/// iOS: Calendar (Events)
static const PermissionGroup calendar = PermissionGroup._(0);
/// Android: Camera
/// iOS: Photos (Camera Roll and Camera)
static const PermissionGroup camera = PermissionGroup._(1);
/// Android: Contacts
/// iOS: AddressBook
static const PermissionGroup contacts = PermissionGroup._(2);
/// Android: Fine and Coarse Location
/// iOS: CoreLocation (Always and WhenInUse)
static const PermissionGroup location = PermissionGroup._(3);
/// Android: Fine and Coarse Location
/// iOS: CoreLocation - Always
static const PermissionGroup locationAlways = PermissionGroup._(4);
/// Android: Fine and Coarse Location
/// iOS: CoreLocation - WhenInUse
static const PermissionGroup locationWhenInUse = PermissionGroup._(5);
/// Android: None
/// iOS: MPMediaLibrary
static const PermissionGroup mediaLibrary = PermissionGroup._(6);
/// Android: Microphone
/// iOS: Microphone
static const PermissionGroup microphone = PermissionGroup._(7);
/// Android: Phone
/// iOS: Nothing
static const PermissionGroup phone = PermissionGroup._(8);
/// Android: Nothing
/// iOS: Photos
static const PermissionGroup photos = PermissionGroup._(9);
/// Android: Nothing
/// iOS: Reminders
static const PermissionGroup reminders = PermissionGroup._(10);
/// Android: Body Sensors
/// iOS: CoreMotion
static const PermissionGroup sensors = PermissionGroup._(11);
/// Android: Sms
/// iOS: Nothing
static const PermissionGroup sms = PermissionGroup._(12);
/// Android: Microphone
/// iOS: Speech
static const PermissionGroup speech = PermissionGroup._(13);
/// Android: External Storage
/// iOS: Nothing
static const PermissionGroup storage = PermissionGroup._(14);
/// The unknown permission only used for return type, never requested
static const PermissionGroup unknown = PermissionGroup._(15);
static const List<PermissionGroup> values = <PermissionGroup>[
calendar,
camera,
contacts,
location,
locationAlways,
locationWhenInUse,
mediaLibrary,
microphone,
phone,
photos,
reminders,
sensors,
sms,
speech,
storage,
unknown,
];
static const List<String> _names = <String>[
'calendar',
'camera',
'contacts',
'location',
'locationAlways',
'locationWhenInUse',
'mediaLibrary',
'microphone',
'phone',
'photos',
'reminders',
'sensors',
'sms',
'speech',
'storage',
'unknown',
];
@override
String toString() => 'PermissionGroup.${_names[value]}';
}
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
import 'package:permission_handler/src/permission_enums.dart';
import 'package:permission_handler/src/utils/codec.dart';
/// Provides a cross-platform (iOS, Android) API to request and check permissions.
class PermissionHandler {
factory PermissionHandler() {
if (_instance == null) {
const MethodChannel methodChannel =
MethodChannel('flutter.baseflow.com/permissions/methods');
_instance = PermissionHandler.private(methodChannel);
}
return _instance;
}
@visibleForTesting
PermissionHandler.private(this._methodChannel);
static PermissionHandler _instance;
final MethodChannel _methodChannel;
/// Check current permission status.
///
/// Returns a [Future] containing the current permission status for the supplied [PermissionGroup].
Future<PermissionStatus> checkPermissionStatus(
PermissionGroup permission) async {
final int status = await _methodChannel.invokeMethod(
'checkPermissionStatus', permission.value);
return Codec.decodePermissionStatus(status);
}
/// Check current service status.
///
/// Returns a [Future] containing the current service status for the supplied [PermissionGroup].
Future<ServiceStatus> checkServiceStatus(PermissionGroup permission) async {
final int status = await _methodChannel.invokeMethod(
'checkServiceStatus', permission.value);
return Codec.decodeServiceStatus(status);
}
/// Open the App settings page.
///
/// Returns [true] if the app settings page could be opened, otherwise [false] is returned.
Future<bool> openAppSettings() async {
final bool hasOpened = await _methodChannel.invokeMethod('openAppSettings');
return hasOpened;
}
/// Request the user for access to the supplied list of permissiongroups.
///
/// Returns a [Map] containing the status per requested permissiongroup.
Future<Map<PermissionGroup, PermissionStatus>> requestPermissions(
List<PermissionGroup> permissions) async {
final List<int> data = Codec.encodePermissionGroups(permissions);
final Map status =
await _methodChannel.invokeMethod('requestPermissions', data);
return Codec.decodePermissionRequestResult(Map<int, int>.from(status));
}
/// Request to see if you should show a rationale for requesting permission.
///
/// This method is only implemented on Android, calling this on iOS always
/// returns [false].
Future<bool> shouldShowRequestPermissionRationale(
PermissionGroup permission) async {
if (!Platform.isAndroid) {
return false;
}
final bool shouldShowRationale = await _methodChannel.invokeMethod(
'shouldShowRequestPermissionRationale', permission.value);
return shouldShowRationale;
}
}
import 'package:permission_handler/src/permission_enums.dart';
class Codec {
static PermissionStatus decodePermissionStatus(int value) {
return PermissionStatus.values[value];
}
static ServiceStatus decodeServiceStatus(int value) {
return ServiceStatus.values[value];
}
static Map<PermissionGroup, PermissionStatus> decodePermissionRequestResult(
Map<int, int> value) {
print('decodePermissionRequestResult called with: value:[$value]');
return value.map((int key, int value) =>
MapEntry<PermissionGroup, PermissionStatus>(
PermissionGroup.values[key], PermissionStatus.values[value]));
}
static List<int> encodePermissionGroups(List<PermissionGroup> permissions) {
return permissions.map((PermissionGroup it) => it.value).toList();
}
}
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