Commit 54382479 by Maurits van Beusekom

Production release 4.0.0

parents 075c83a7 dbf301a9
## 4.0.0
* iOS: Added support for requesting permissions on the DOCUMENTS and DOWNLOADS folder (thanks to @phranck);
* Androis: Fix the PROCESS_OUTGOING_CALLS permissions which have been deprecated in API 29.
## 3.3.0
* Android: Add support for requesting the background location permission within the `locationAlways` group.
......
......@@ -37,7 +37,7 @@ We really appreciate contributions via GitHub pull requests. To contribute take
* Apply your changes
* Verify your changes and fix potential warnings/ errors:
* Check formatting: `flutter format .`
* Run static analyses: `flutter analyzes`
* Run static analyses: `flutter analyze`
* Run unit-tests: `flutter test`
* Commit your changes: `git commit -am "<your informative commit message>"`
* Push changes to your fork: `git push origin <name_of_your_branch>`
......
......@@ -22,7 +22,7 @@ To use this plugin, add `permission_handler` as a [dependency in your pubspec.ya
```yaml
dependencies:
permission_handler: '^3.3.0'
permission_handler: '^4.0.0'
```
> **NOTE:** As of version 3.1.0 the permission_handler plugin switched to the AndroidX version of the Android Support Libraries. This means you need to make sure your Android project is also upgraded to support AndroidX. Detailed instructions can be found [here](https://flutter.dev/docs/development/packages-and-plugins/androidx-compatibility).
......@@ -169,6 +169,10 @@ enum PermissionGroup {
/// Android: None
/// iOS: MPMediaLibrary
mediaLibrary
/// Android: Check notification enable
/// iOS: Check and request notification permission
notification
}
```
......
......@@ -19,6 +19,7 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import androidx.core.app.NotificationManagerCompat;
import io.flutter.plugin.common.PluginRegistry.ActivityResultListener;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
......@@ -60,7 +61,8 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
private static final int PERMISSION_GROUP_SPEECH = 13;
private static final int PERMISSION_GROUP_STORAGE = 14;
private static final int PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS = 15;
private static final int PERMISSION_GROUP_UNKNOWN = 16;
private static final int PERMISSION_GROUP_NOTIFICATION = 16;
private static final int PERMISSION_GROUP_UNKNOWN = 17;
private PermissionHandlerPlugin(Registrar mRegistrar) {
this.mRegistrar = mRegistrar;
......@@ -84,6 +86,7 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
PERMISSION_GROUP_SPEECH,
PERMISSION_GROUP_STORAGE,
PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS,
PERMISSION_GROUP_NOTIFICATION,
PERMISSION_GROUP_UNKNOWN,
})
private @interface PermissionGroup {
......@@ -179,7 +182,7 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
case Manifest.permission.WRITE_CALL_LOG:
case Manifest.permission.ADD_VOICEMAIL:
case Manifest.permission.USE_SIP:
case Manifest.permission.PROCESS_OUTGOING_CALLS:
case Manifest.permission.BIND_CALL_REDIRECTION_SERVICE:
return PERMISSION_GROUP_PHONE;
case Manifest.permission.BODY_SENSORS:
return PERMISSION_GROUP_SENSORS;
......@@ -250,6 +253,16 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
@PermissionStatus
private int checkPermissionStatus(@PermissionGroup int permission) {
final Context context = mRegistrar.activity() == null ? mRegistrar.activeContext() : mRegistrar.activity();
if (context == null) {
Log.d(LOG_TAG, "Unable to detect current Activity or App Context.");
return PERMISSION_STATUS_UNKNOWN;
}
if (permission == PERMISSION_GROUP_NOTIFICATION) {
return checkNotificationPermissionStatus(context);
}
final List<String> names = getManifestNames(permission);
if (names == null) {
......@@ -264,12 +277,6 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
return PERMISSION_STATUS_UNKNOWN;
}
final Context context = mRegistrar.activity() == null ? mRegistrar.activeContext() : mRegistrar.activity();
if (context == null) {
Log.d(LOG_TAG, "Unable to detect current Activity or App Context.");
return PERMISSION_STATUS_UNKNOWN;
}
final boolean targetsMOrHigher = context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.M;
for (String name : names) {
......@@ -613,8 +620,9 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
if (hasPermissionInManifest(Manifest.permission.USE_SIP))
permissionNames.add(Manifest.permission.USE_SIP);
if (hasPermissionInManifest(Manifest.permission.PROCESS_OUTGOING_CALLS))
permissionNames.add(Manifest.permission.PROCESS_OUTGOING_CALLS);
if (hasPermissionInManifest(Manifest.permission.BIND_CALL_REDIRECTION_SERVICE))
permissionNames.add(Manifest.permission.BIND_CALL_REDIRECTION_SERVICE);
break;
case PERMISSION_GROUP_SENSORS:
......@@ -655,6 +663,7 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
permissionNames.add(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
break;
case PERMISSION_GROUP_NOTIFICATION:
case PERMISSION_GROUP_MEDIA_LIBRARY:
case PERMISSION_GROUP_PHOTOS:
case PERMISSION_GROUP_REMINDERS:
......@@ -726,4 +735,13 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
return !TextUtils.isEmpty(locationProviders);
}
}
private int checkNotificationPermissionStatus(Context context) {
NotificationManagerCompat manager = NotificationManagerCompat.from(context);
boolean isGranted = manager.areNotificationsEnabled();
if (isGranted) {
return PERMISSION_STATUS_GRANTED;
}
return PERMISSION_STATUS_DENIED;
}
}
......@@ -34,7 +34,7 @@
<uses-permission android:name="android.permission.USE_SIP"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.BIND_CALL_REDIRECTION_SERVICE"/>
<!-- Permissions options for the `calendar` group -->
<uses-permission android:name="android.permission.READ_CALENDAR" />
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array/>
</dict>
</plist>
......@@ -22,6 +22,7 @@ typedef NS_ENUM(int, PermissionGroup) {
PermissionGroupSpeech,
PermissionGroupStorage,
PermissionGroupIgnoreBatteryOptimizations,
PermissionGroupNotification,
PermissionGroupUnknown,
};
......
......@@ -19,7 +19,9 @@
#import "PhotoPermissionStrategy.h"
#import "SensorPermissionStrategy.h"
#import "SpeechPermissionStrategy.h"
#import "StoragePermissionStrategy.h"
#import "UnknownPermissionStrategy.h"
#import "NotificationPermissionStrategy.h"
#import "PermissionHandlerEnums.h"
#import "Codec.h"
......@@ -28,13 +30,10 @@ typedef void (^PermissionRequestCompletion)(NSDictionary *permissionRequestResul
@interface PermissionManager : NSObject
- (instancetype)initWithStrategyInstances;
- (void)requestPermissions:(NSArray *)permissions completion:(PermissionRequestCompletion)completion;
+ (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
......@@ -99,6 +99,10 @@
return [SensorPermissionStrategy new];
case PermissionGroupSpeech:
return [SpeechPermissionStrategy new];
case PermissionGroupNotification:
return [NotificationPermissionStrategy new];
case PermissionGroupStorage:
return [StoragePermissionStrategy new];
default:
return [UnknownPermissionStrategy new];
}
......
//
// NotificationPermissionStrategy.h
// permission_handler
//
// Created by Tong on 2019/10/21.
//
#import <Foundation/Foundation.h>
#import <UserNotifications/UserNotifications.h>
#import "PermissionStrategy.h"
@interface NotificationPermissionStrategy : NSObject <PermissionStrategy>
@end
//
// NotificationPermissionStrategy.m
// permission_handler
//
// Created by Tong on 2019/10/21.
//
#import "NotificationPermissionStrategy.h"
@implementation NotificationPermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
return [NotificationPermissionStrategy 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;
}
dispatch_async(dispatch_get_main_queue(), ^{
if(@available(iOS 10.0, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
UNAuthorizationOptions authorizationOptions = 0;
authorizationOptions += UNAuthorizationOptionSound;
authorizationOptions += UNAuthorizationOptionAlert;
authorizationOptions += UNAuthorizationOptionBadge;
[center requestAuthorizationWithOptions:(authorizationOptions) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!granted || error != nil) {
completionHandler(PermissionStatusDenied);
return;
}
}];
} else {
UIUserNotificationType notificationTypes = 0;
notificationTypes |= UIUserNotificationTypeSound;
notificationTypes |= UIUserNotificationTypeAlert;
notificationTypes |= UIUserNotificationTypeBadge;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
[[UIApplication sharedApplication] registerForRemoteNotifications];
completionHandler(PermissionStatusGranted);
});
}
+ (PermissionStatus)permissionStatus {
__block PermissionStatus permissionStatus = PermissionStatusGranted;
if (@available(iOS 10 , *)) {
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
if (settings.authorizationStatus == UNAuthorizationStatusDenied) {
permissionStatus = PermissionStatusDenied;
} else if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined) {
permissionStatus = PermissionStatusUnknown;
}
dispatch_semaphore_signal(sem);
}];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
} else if (@available(iOS 8 , *)) {
UIUserNotificationSettings * setting = [[UIApplication sharedApplication] currentUserNotificationSettings];
if (setting.types == UIUserNotificationTypeNone) permissionStatus = PermissionStatusDenied;
} else {
UIRemoteNotificationType type = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (type == UIUserNotificationTypeNone) permissionStatus = PermissionStatusDenied;
}
return permissionStatus;
}
@end
//
// StoragePermissionStrategy.h
// permission_handler
//
// Created by Frank Gregor on 06.11.19.
//
#import <Foundation/Foundation.h>
#import "PermissionStrategy.h"
NS_ASSUME_NONNULL_BEGIN
@interface StoragePermissionStrategy : NSObject <PermissionStrategy>
@end
NS_ASSUME_NONNULL_END
//
// StoragePermissionStrategy.m
// permission_handler
//
// Created by Frank Gregor on 06.11.19.
//
#import "StoragePermissionStrategy.h"
@implementation StoragePermissionStrategy
- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission {
return [StoragePermissionStrategy permissionStatus];
}
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return ServiceStatusNotApplicable;
}
- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler {
completionHandler([StoragePermissionStrategy permissionStatus]);
}
+ (PermissionStatus)permissionStatus {
return PermissionStatusGranted;
}
@end
......@@ -3,10 +3,10 @@
#
Pod::Spec.new do |s|
s.name = 'permission_handler'
s.version = '3.3.0'
s.version = '4.0.0'
s.summary = 'Permission plugin for Flutter.'
s.description = <<-DESC
A new Flutter project.
Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
DESC
s.homepage = 'https://github.com/baseflowit/flutter-permission-handler'
s.license = { :file => '../LICENSE' }
......
......@@ -142,15 +142,19 @@ class PermissionGroup {
static const PermissionGroup speech = PermissionGroup._(13);
/// Android: External Storage
/// iOS: Nothing
/// iOS: Access to folders like `Documents` or `Downloads`. Implicitly granted.
static const PermissionGroup storage = PermissionGroup._(14);
/// Android: Ignore Battery Optimizations
static const PermissionGroup ignoreBatteryOptimizations =
PermissionGroup._(15);
/// Android: Notification
/// iOS: Notification
static const PermissionGroup notification = PermissionGroup._(16);
/// The unknown permission only used for return type, never requested
static const PermissionGroup unknown = PermissionGroup._(16);
static const PermissionGroup unknown = PermissionGroup._(17);
static const List<PermissionGroup> values = <PermissionGroup>[
calendar,
......@@ -169,6 +173,7 @@ class PermissionGroup {
speech,
storage,
ignoreBatteryOptimizations,
notification,
unknown,
];
......@@ -189,6 +194,7 @@ class PermissionGroup {
'speech',
'storage',
'ignoreBatteryOptimizations',
'notification',
'unknown',
];
......
name: permission_handler
description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
version: 3.3.0
version: 4.0.0
authors:
- Baseflow <hello@baseflow.com>
- long1eu <home@long1.eu>
......
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