Commit 5b394f2d by Neal Soni

Add notificationPolicy permission on Android

parent b769baba
## 8.1.0
* 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
......
......@@ -139,11 +139,11 @@ You must list permission you want to use in your application :
| PermissionGroup.photos | NSPhotoLibraryUsageDescription | PERMISSION_PHOTOS |
| PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse | NSLocationUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription, NSLocationWhenInUseUsageDescription | PERMISSION_LOCATION |
| PermissionGroup.notification | PermissionGroupNotification | PERMISSION_NOTIFICATIONS |
| PermissionGroup.criticalAlerts | PermissionGroupCriticalAlerts | PERMISSION_CRITICAL_ALERTS |
| PermissionGroup.mediaLibrary | NSAppleMusicUsageDescription, kTCCServiceMediaLibrary | PERMISSION_MEDIA_LIBRARY |
| PermissionGroup.sensors | NSMotionUsageDescription | PERMISSION_SENSORS |
| PermissionGroup.bluetooth | NSBluetoothAlwaysUsageDescription, NSBluetoothPeripheralUsageDescription | PERMISSION_BLUETOOTH |
| PermissionGroup.appTrackingTransparency | NSUserTrackingUsageDescription | PERMISSION_APP_TRACKING_TRANSPARENCY |
| PermissionGroup.criticalAlerts | PermissionGroupCriticalAlerts | PERMISSION_CRITICAL_ALERTS |
4. Clean & Rebuild
</details>
......@@ -223,6 +223,7 @@ The following permissions will show no dialog, but will open the corresponding s
- manageExternalStorage
- systemAlertWindow
- requestInstallPackages
- accessNotificationPolicy
## Issues
......
......@@ -12,6 +12,7 @@ final class PermissionConstants {
static final int PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE = 210;
static final int PERMISSION_CODE_SYSTEM_ALERT_WINDOW = 211;
static final int PERMISSION_CODE_REQUEST_INSTALL_PACKAGES = 212;
static final int PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY = 213;
//PERMISSION_GROUP
static final int PERMISSION_GROUP_CALENDAR = 0;
......@@ -39,6 +40,9 @@ final class PermissionConstants {
static final int PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE = 22;
static final int PERMISSION_GROUP_SYSTEM_ALERT_WINDOW = 23;
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)
@IntDef({
......@@ -65,7 +69,8 @@ final class PermissionConstants {
PERMISSION_GROUP_BLUETOOTH,
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE,
PERMISSION_GROUP_SYSTEM_ALERT_WINDOW,
PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES
PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES,
PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY
})
@interface PermissionGroup {
}
......
package com.baseflow.permissionhandler;
import android.app.Activity;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
......@@ -38,7 +41,8 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
if (requestCode != PermissionConstants.PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS &&
requestCode != PermissionConstants.PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE &&
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;
}
......@@ -73,6 +77,16 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
} else {
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 {
return false;
}
......@@ -255,6 +269,10 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
executeIntent(
Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
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 {
permissionsToRequest.addAll(names);
}
......@@ -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 (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
// 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,
}
}
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);
if (permissionStatus != PackageManager.PERMISSION_GRANTED) {
return PermissionConstants.PERMISSION_STATUS_DENIED;
......@@ -382,6 +409,10 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
activity.startActivityForResult(intent, requestCode);
}
private void executeSimpleIntent(String action, int requestCode) {
activity.startActivityForResult(new Intent(action), requestCode);
}
void shouldShowRequestPermissionRationale(
int permission,
Activity activity,
......
......@@ -67,6 +67,8 @@ public class PermissionUtils {
return PermissionConstants.PERMISSION_GROUP_SYSTEM_ALERT_WINDOW;
case Manifest.permission.REQUEST_INSTALL_PACKAGES:
return PermissionConstants.PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES;
case Manifest.permission.ACCESS_NOTIFICATION_POLICY:
return PermissionConstants.PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY;
default:
return PermissionConstants.PERMISSION_GROUP_UNKNOWN;
}
......@@ -239,7 +241,12 @@ public class PermissionUtils {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.REQUEST_INSTALL_PACKAGES ))
permissionNames.add(Manifest.permission.REQUEST_INSTALL_PACKAGES);
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_MEDIA_LIBRARY:
case PermissionConstants.PERMISSION_GROUP_PHOTOS:
......
......@@ -72,6 +72,9 @@
<!-- Permissions options for the `request install packages` group -->
<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
android:name="io.flutter.app.FlutterApplication"
android:icon="@mipmap/ic_launcher"
......
......@@ -46,4 +46,7 @@
<!-- Permissions options for the `sensors` group -->
<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>
......@@ -44,14 +44,16 @@ class _PermissionHandlerWidgetState extends State<PermissionHandlerWidget> {
permission != Permission.activityRecognition &&
permission != Permission.manageExternalStorage &&
permission != Permission.systemAlertWindow &&
permission != Permission.requestInstallPackages;
permission != Permission.requestInstallPackages &&
permission != Permission.accessNotificationPolicy;
} else {
return permission != Permission.unknown &&
permission != Permission.mediaLibrary &&
permission != Permission.photos &&
permission != Permission.photosAddOnly &&
permission != Permission.reminders &&
permission != Permission.appTrackingTransparency;
permission != Permission.appTrackingTransparency &&
permission != Permission.criticalAlerts;
}
})
.map((permission) => PermissionWidget(permission))
......
......@@ -104,6 +104,7 @@
// ios: PermissionGroupCriticalAlerts
// Info.plist: UNAuthorizationOptionCriticalAlert
// dart: PermissionGroup.criticalAlerts
#ifndef PERMISSION_CRITICAL_ALERTS
#define PERMISSION_CRITICAL_ALERTS 0
......@@ -136,7 +137,8 @@ typedef NS_ENUM(int, PermissionGroup) {
PermissionGroupSystemAlertWindow,
PermissionGroupRequestInstallPackages,
PermissionGroupAppTrackingTransparency,
PermissionGroupCriticalAlerts
PermissionGroupCriticalAlerts,
PermissionGroupAccessNotificationPolicy,
};
typedef NS_ENUM(int, PermissionStatus) {
......
......@@ -147,7 +147,6 @@ class Permission {
///iOS: Notifications that override your ringer
static const criticalAlerts = Permission._(26);
/// Returns a list of all possible [PermissionGroup] values.
static const List<Permission> values = <Permission>[
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