Commit 5b394f2d by Neal Soni

Add notificationPolicy permission on Android

parent b769baba
## 8.1.0 ## 8.1.0
* Added support for iOS 12+ Critical Alerts permission requesting. * Added support for iOS 12+ Critical Alerts permission requesting.
* NOTE: This requires applying to Apple and recieving a special entitlement from them inorder to work. See [this article](https://medium.com/@shashidharyamsani/implementing-ios-critical-alerts-7d82b4bb5026) for an explination on how to use Critical Alerts. * NOTE: This requires applying to Apple and recieving a special entitlement from them inorder to work. See [this article](https://medium.com/@shashidharyamsani/implementing-ios-critical-alerts-7d82b4bb5026) for an explination on how to use Critical Alerts.
* Added support for Android M+ Access Notification Policy permission requesting (ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS).
* Note: This opens a general page in settings, not specific to the package.
## 8.0.1 ## 8.0.1
......
...@@ -139,11 +139,11 @@ You must list permission you want to use in your application : ...@@ -139,11 +139,11 @@ You must list permission you want to use in your application :
| PermissionGroup.photos | NSPhotoLibraryUsageDescription | PERMISSION_PHOTOS | | PermissionGroup.photos | NSPhotoLibraryUsageDescription | PERMISSION_PHOTOS |
| PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse | NSLocationUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription, NSLocationWhenInUseUsageDescription | PERMISSION_LOCATION | | PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse | NSLocationUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription, NSLocationWhenInUseUsageDescription | PERMISSION_LOCATION |
| PermissionGroup.notification | PermissionGroupNotification | PERMISSION_NOTIFICATIONS | | PermissionGroup.notification | PermissionGroupNotification | PERMISSION_NOTIFICATIONS |
| PermissionGroup.criticalAlerts | PermissionGroupCriticalAlerts | PERMISSION_CRITICAL_ALERTS |
| PermissionGroup.mediaLibrary | NSAppleMusicUsageDescription, kTCCServiceMediaLibrary | PERMISSION_MEDIA_LIBRARY | | PermissionGroup.mediaLibrary | NSAppleMusicUsageDescription, kTCCServiceMediaLibrary | PERMISSION_MEDIA_LIBRARY |
| PermissionGroup.sensors | NSMotionUsageDescription | PERMISSION_SENSORS | | PermissionGroup.sensors | NSMotionUsageDescription | PERMISSION_SENSORS |
| PermissionGroup.bluetooth | NSBluetoothAlwaysUsageDescription, NSBluetoothPeripheralUsageDescription | PERMISSION_BLUETOOTH | | PermissionGroup.bluetooth | NSBluetoothAlwaysUsageDescription, NSBluetoothPeripheralUsageDescription | PERMISSION_BLUETOOTH |
| PermissionGroup.appTrackingTransparency | NSUserTrackingUsageDescription | PERMISSION_APP_TRACKING_TRANSPARENCY | | PermissionGroup.appTrackingTransparency | NSUserTrackingUsageDescription | PERMISSION_APP_TRACKING_TRANSPARENCY |
| PermissionGroup.criticalAlerts | PermissionGroupCriticalAlerts | PERMISSION_CRITICAL_ALERTS |
4. Clean & Rebuild 4. Clean & Rebuild
</details> </details>
...@@ -223,6 +223,7 @@ The following permissions will show no dialog, but will open the corresponding s ...@@ -223,6 +223,7 @@ The following permissions will show no dialog, but will open the corresponding s
- manageExternalStorage - manageExternalStorage
- systemAlertWindow - systemAlertWindow
- requestInstallPackages - requestInstallPackages
- accessNotificationPolicy
## Issues ## Issues
......
...@@ -12,6 +12,7 @@ final class PermissionConstants { ...@@ -12,6 +12,7 @@ final class PermissionConstants {
static final int PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE = 210; static final int PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE = 210;
static final int PERMISSION_CODE_SYSTEM_ALERT_WINDOW = 211; static final int PERMISSION_CODE_SYSTEM_ALERT_WINDOW = 211;
static final int PERMISSION_CODE_REQUEST_INSTALL_PACKAGES = 212; static final int PERMISSION_CODE_REQUEST_INSTALL_PACKAGES = 212;
static final int PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY = 213;
//PERMISSION_GROUP //PERMISSION_GROUP
static final int PERMISSION_GROUP_CALENDAR = 0; static final int PERMISSION_GROUP_CALENDAR = 0;
...@@ -39,6 +40,9 @@ final class PermissionConstants { ...@@ -39,6 +40,9 @@ final class PermissionConstants {
static final int PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE = 22; static final int PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE = 22;
static final int PERMISSION_GROUP_SYSTEM_ALERT_WINDOW = 23; static final int PERMISSION_GROUP_SYSTEM_ALERT_WINDOW = 23;
static final int PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES = 24; static final int PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES = 24;
static final int PERMISSION_GROUP_APP_TRACK_TRANSPARENCY = 25;
static final int PERMISSION_GROUP_CRITICAL_ALERTS = 26;
static final int PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY = 27;
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({ @IntDef({
...@@ -65,7 +69,8 @@ final class PermissionConstants { ...@@ -65,7 +69,8 @@ final class PermissionConstants {
PERMISSION_GROUP_BLUETOOTH, PERMISSION_GROUP_BLUETOOTH,
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE, PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE,
PERMISSION_GROUP_SYSTEM_ALERT_WINDOW, PERMISSION_GROUP_SYSTEM_ALERT_WINDOW,
PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES,
PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY
}) })
@interface PermissionGroup { @interface PermissionGroup {
} }
......
package com.baseflow.permissionhandler; package com.baseflow.permissionhandler;
import android.app.Activity; import android.app.Activity;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
...@@ -38,7 +41,8 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -38,7 +41,8 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
if (requestCode != PermissionConstants.PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS && if (requestCode != PermissionConstants.PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS &&
requestCode != PermissionConstants.PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE && requestCode != PermissionConstants.PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE &&
requestCode != PermissionConstants.PERMISSION_CODE_SYSTEM_ALERT_WINDOW && requestCode != PermissionConstants.PERMISSION_CODE_SYSTEM_ALERT_WINDOW &&
requestCode != PermissionConstants.PERMISSION_CODE_REQUEST_INSTALL_PACKAGES) { requestCode != PermissionConstants.PERMISSION_CODE_REQUEST_INSTALL_PACKAGES &&
requestCode != PermissionConstants.PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY) {
return false; return false;
} }
...@@ -73,6 +77,16 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -73,6 +77,16 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
} else { } else {
return false; return false;
} }
} else if (requestCode == PermissionConstants.PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
NotificationManager notificationManager = (NotificationManager) activity.getSystemService(Application.NOTIFICATION_SERVICE);
status = notificationManager.isNotificationPolicyAccessGranted()
? PermissionConstants.PERMISSION_STATUS_GRANTED
: PermissionConstants.PERMISSION_STATUS_DENIED;
permission = PermissionConstants.PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY;
} else {
return false;
}
} else { } else {
return false; return false;
} }
...@@ -255,6 +269,10 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -255,6 +269,10 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
executeIntent( executeIntent(
Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
PermissionConstants.PERMISSION_CODE_REQUEST_INSTALL_PACKAGES); PermissionConstants.PERMISSION_CODE_REQUEST_INSTALL_PACKAGES);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && permission == PermissionConstants.PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY) {
executeSimpleIntent(
Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS,
PermissionConstants.PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY);
} else { } else {
permissionsToRequest.addAll(names); permissionsToRequest.addAll(names);
} }
...@@ -298,7 +316,7 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -298,7 +316,7 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
//if no permissions were found then there is an issue and permission is not set in Android manifest //if no permissions were found then there is an issue and permission is not set in Android manifest
if (names.size() == 0) { if (names.size() == 0) {
Log.d(PermissionConstants.LOG_TAG, "No permissions found in manifest for: " + permission); Log.d(PermissionConstants.LOG_TAG, "No permissions found in manifest for: " + names + permission);
// On Android below M, the android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS flag in AndroidManifest.xml // On Android below M, the android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS flag in AndroidManifest.xml
// may be ignored and not visible to the App as it's a new permission setting as a whole. // may be ignored and not visible to the App as it's a new permission setting as a whole.
...@@ -365,6 +383,15 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -365,6 +383,15 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
} }
} }
if (permission == PermissionConstants.PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Application.NOTIFICATION_SERVICE);
return notificationManager.isNotificationPolicyAccessGranted()
? PermissionConstants.PERMISSION_STATUS_GRANTED
: PermissionConstants.PERMISSION_STATUS_DENIED;
}
}
final int permissionStatus = ContextCompat.checkSelfPermission(context, name); final int permissionStatus = ContextCompat.checkSelfPermission(context, name);
if (permissionStatus != PackageManager.PERMISSION_GRANTED) { if (permissionStatus != PackageManager.PERMISSION_GRANTED) {
return PermissionConstants.PERMISSION_STATUS_DENIED; return PermissionConstants.PERMISSION_STATUS_DENIED;
...@@ -382,6 +409,10 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -382,6 +409,10 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
activity.startActivityForResult(intent, requestCode); activity.startActivityForResult(intent, requestCode);
} }
private void executeSimpleIntent(String action, int requestCode) {
activity.startActivityForResult(new Intent(action), requestCode);
}
void shouldShowRequestPermissionRationale( void shouldShowRequestPermissionRationale(
int permission, int permission,
Activity activity, Activity activity,
......
...@@ -67,6 +67,8 @@ public class PermissionUtils { ...@@ -67,6 +67,8 @@ public class PermissionUtils {
return PermissionConstants.PERMISSION_GROUP_SYSTEM_ALERT_WINDOW; return PermissionConstants.PERMISSION_GROUP_SYSTEM_ALERT_WINDOW;
case Manifest.permission.REQUEST_INSTALL_PACKAGES: case Manifest.permission.REQUEST_INSTALL_PACKAGES:
return PermissionConstants.PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES; return PermissionConstants.PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES;
case Manifest.permission.ACCESS_NOTIFICATION_POLICY:
return PermissionConstants.PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY;
default: default:
return PermissionConstants.PERMISSION_GROUP_UNKNOWN; return PermissionConstants.PERMISSION_GROUP_UNKNOWN;
} }
...@@ -239,7 +241,12 @@ public class PermissionUtils { ...@@ -239,7 +241,12 @@ public class PermissionUtils {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.REQUEST_INSTALL_PACKAGES )) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.REQUEST_INSTALL_PACKAGES ))
permissionNames.add(Manifest.permission.REQUEST_INSTALL_PACKAGES); permissionNames.add(Manifest.permission.REQUEST_INSTALL_PACKAGES);
break; break;
case PermissionConstants.PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY:
// The REQUEST_NOTIFICATION_POLICY permission is introduced in Android M, meaning we should
// not handle permissions on pre Android M devices.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_NOTIFICATION_POLICY ))
permissionNames.add(Manifest.permission.ACCESS_NOTIFICATION_POLICY);
break;
case PermissionConstants.PERMISSION_GROUP_NOTIFICATION: case PermissionConstants.PERMISSION_GROUP_NOTIFICATION:
case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY: case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY:
case PermissionConstants.PERMISSION_GROUP_PHOTOS: case PermissionConstants.PERMISSION_GROUP_PHOTOS:
......
...@@ -72,6 +72,9 @@ ...@@ -72,6 +72,9 @@
<!-- Permissions options for the `request install packages` group --> <!-- Permissions options for the `request install packages` group -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- Permissions options for the `access notification policy` group -->
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
<application <application
android:name="io.flutter.app.FlutterApplication" android:name="io.flutter.app.FlutterApplication"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
......
...@@ -46,4 +46,7 @@ ...@@ -46,4 +46,7 @@
<!-- Permissions options for the `sensors` group --> <!-- Permissions options for the `sensors` group -->
<uses-permission android:name="android.permission.BODY_SENSORS" /> <uses-permission android:name="android.permission.BODY_SENSORS" />
<!-- Permissions options for the `access notification policy` group -->
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
</manifest> </manifest>
...@@ -44,14 +44,16 @@ class _PermissionHandlerWidgetState extends State<PermissionHandlerWidget> { ...@@ -44,14 +44,16 @@ class _PermissionHandlerWidgetState extends State<PermissionHandlerWidget> {
permission != Permission.activityRecognition && permission != Permission.activityRecognition &&
permission != Permission.manageExternalStorage && permission != Permission.manageExternalStorage &&
permission != Permission.systemAlertWindow && permission != Permission.systemAlertWindow &&
permission != Permission.requestInstallPackages; permission != Permission.requestInstallPackages &&
permission != Permission.accessNotificationPolicy;
} else { } else {
return permission != Permission.unknown && return permission != Permission.unknown &&
permission != Permission.mediaLibrary && permission != Permission.mediaLibrary &&
permission != Permission.photos && permission != Permission.photos &&
permission != Permission.photosAddOnly && permission != Permission.photosAddOnly &&
permission != Permission.reminders && permission != Permission.reminders &&
permission != Permission.appTrackingTransparency; permission != Permission.appTrackingTransparency &&
permission != Permission.criticalAlerts;
} }
}) })
.map((permission) => PermissionWidget(permission)) .map((permission) => PermissionWidget(permission))
......
...@@ -104,6 +104,7 @@ ...@@ -104,6 +104,7 @@
// ios: PermissionGroupCriticalAlerts // ios: PermissionGroupCriticalAlerts
// Info.plist: UNAuthorizationOptionCriticalAlert
// dart: PermissionGroup.criticalAlerts // dart: PermissionGroup.criticalAlerts
#ifndef PERMISSION_CRITICAL_ALERTS #ifndef PERMISSION_CRITICAL_ALERTS
#define PERMISSION_CRITICAL_ALERTS 0 #define PERMISSION_CRITICAL_ALERTS 0
...@@ -136,7 +137,8 @@ typedef NS_ENUM(int, PermissionGroup) { ...@@ -136,7 +137,8 @@ typedef NS_ENUM(int, PermissionGroup) {
PermissionGroupSystemAlertWindow, PermissionGroupSystemAlertWindow,
PermissionGroupRequestInstallPackages, PermissionGroupRequestInstallPackages,
PermissionGroupAppTrackingTransparency, PermissionGroupAppTrackingTransparency,
PermissionGroupCriticalAlerts PermissionGroupCriticalAlerts,
PermissionGroupAccessNotificationPolicy,
}; };
typedef NS_ENUM(int, PermissionStatus) { typedef NS_ENUM(int, PermissionStatus) {
......
...@@ -147,7 +147,6 @@ class Permission { ...@@ -147,7 +147,6 @@ class Permission {
///iOS: Notifications that override your ringer ///iOS: Notifications that override your ringer
static const criticalAlerts = Permission._(26); static const criticalAlerts = Permission._(26);
/// Returns a list of all possible [PermissionGroup] values. /// Returns a list of all possible [PermissionGroup] values.
static const List<Permission> values = <Permission>[ static const List<Permission> values = <Permission>[
calendar, calendar,
......
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