Commit 78604e7f by Jeroen Weener Committed by GitHub

Enhancement/split bind call redirection service permission (#1157)

* Remove `BIND_CALL_REDIRECTION_SERVICE` permission from `PERMISSION_GROUP_PHONE`

* Remove `BIND_CALL_REDIRECTION_SERVICE` permission from manifest

* Combine all permission results instead of returning the first

* Update changelog and version

* Update CHANGELOG and version
parent a021685f
## 11.0.2
* Fixes a bug where `Permission.Phone` would always return 'denied' when requesting the permission status.
* Fixes a bug where Flutter permissions that require multiple Android permissions would base their status on the status of the first Android permission, as opposed to the result of all relevant Android permissions.
## 11.0.1
* Fixes `java.lang.IllegalStateException: Reply already submitted` when requesting post notification permission.
......
......@@ -2,8 +2,10 @@ package com.baseflow.permissionhandler;
import androidx.annotation.IntDef;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
final class PermissionConstants {
static final String LOG_TAG = "permissions_handler";
......@@ -99,6 +101,7 @@ final class PermissionConstants {
static final int PERMISSION_STATUS_LIMITED = 3;
static final int PERMISSION_STATUS_NEVER_ASK_AGAIN = 4;
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.SOURCE)
@IntDef({
PERMISSION_STATUS_DENIED,
......
package com.baseflow.permissionhandler;
import static com.baseflow.permissionhandler.PermissionUtils.strictestStatus;
import android.Manifest;
import android.app.Activity;
import android.app.AlarmManager;
......@@ -23,8 +25,10 @@ import androidx.core.content.ContextCompat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import io.flutter.plugin.common.PluginRegistry;
......@@ -177,7 +181,12 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
final int result = grantResults[i];
if (permission == PermissionConstants.PERMISSION_GROUP_MICROPHONE) {
if (permission == PermissionConstants.PERMISSION_GROUP_PHONE) {
@Nullable @PermissionConstants.PermissionStatus Integer previousResult = requestResults.get(PermissionConstants.PERMISSION_GROUP_PHONE);
@PermissionConstants.PermissionStatus int newResult = PermissionUtils.toPermissionStatus(this.activity, permissionName, result);
@Nullable @PermissionConstants.PermissionStatus Integer strictestStatus = strictestStatus(previousResult, newResult);
requestResults.put(PermissionConstants.PERMISSION_GROUP_PHONE, strictestStatus);
} else if (permission == PermissionConstants.PERMISSION_GROUP_MICROPHONE) {
if (!requestResults.containsKey(PermissionConstants.PERMISSION_GROUP_MICROPHONE)) {
requestResults.put(
PermissionConstants.PERMISSION_GROUP_MICROPHONE,
......@@ -451,6 +460,7 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
final boolean targetsMOrHigher = context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.M;
Set<@PermissionConstants.PermissionStatus Integer> permissionStatuses = new HashSet<>();
for (String name : names) {
// Only handle them if the client app actually targets a API level greater than M.
if (targetsMOrHigher) {
......@@ -460,67 +470,76 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
// PowerManager.isIgnoringBatteryOptimizations has been included in Android M first.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (pm != null && pm.isIgnoringBatteryOptimizations(packageName)) {
return PermissionConstants.PERMISSION_STATUS_GRANTED;
permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_GRANTED);
} else {
return PermissionConstants.PERMISSION_STATUS_DENIED;
permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_DENIED);
}
} else {
return PermissionConstants.PERMISSION_STATUS_RESTRICTED;
permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_RESTRICTED);
}
}
if (permission == PermissionConstants.PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
return PermissionConstants.PERMISSION_STATUS_RESTRICTED;
permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_RESTRICTED);
}
return Environment.isExternalStorageManager()
int status = Environment.isExternalStorageManager()
? PermissionConstants.PERMISSION_STATUS_GRANTED
: PermissionConstants.PERMISSION_STATUS_DENIED;
permissionStatuses.add(status);
}
if (permission == PermissionConstants.PERMISSION_GROUP_SYSTEM_ALERT_WINDOW) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return Settings.canDrawOverlays(context)
int status = Settings.canDrawOverlays(context)
? PermissionConstants.PERMISSION_STATUS_GRANTED
: PermissionConstants.PERMISSION_STATUS_DENIED;
permissionStatuses.add(status);
}
}
if (permission == PermissionConstants.PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return context.getPackageManager().canRequestPackageInstalls()
int status = context.getPackageManager().canRequestPackageInstalls()
? PermissionConstants.PERMISSION_STATUS_GRANTED
: PermissionConstants.PERMISSION_STATUS_DENIED;
permissionStatuses.add(status);
}
}
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()
int status = notificationManager.isNotificationPolicyAccessGranted()
? PermissionConstants.PERMISSION_STATUS_GRANTED
: PermissionConstants.PERMISSION_STATUS_DENIED;
permissionStatuses.add(status);
}
}
if (permission == PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
return alarmManager.canScheduleExactAlarms()
int status = alarmManager.canScheduleExactAlarms()
? PermissionConstants.PERMISSION_STATUS_GRANTED
: PermissionConstants.PERMISSION_STATUS_DENIED;
permissionStatuses.add(status);
} else {
return PermissionConstants.PERMISSION_STATUS_GRANTED;
permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_GRANTED);
}
}
final int permissionStatus = ContextCompat.checkSelfPermission(context, name);
if (permissionStatus != PackageManager.PERMISSION_GRANTED) {
return PermissionUtils.determineDeniedVariant(activity, name);
permissionStatuses.add(PermissionUtils.determineDeniedVariant(activity, name));
}
}
}
if (!permissionStatuses.isEmpty()) {
return strictestStatus(permissionStatuses);
}
return PermissionConstants.PERMISSION_STATUS_GRANTED;
}
......
......@@ -17,6 +17,8 @@ import androidx.core.app.ActivityCompat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
public class PermissionUtils {
......@@ -48,7 +50,6 @@ public class PermissionUtils {
case Manifest.permission.WRITE_CALL_LOG:
case Manifest.permission.ADD_VOICEMAIL:
case Manifest.permission.USE_SIP:
case Manifest.permission.BIND_CALL_REDIRECTION_SERVICE:
return PermissionConstants.PERMISSION_GROUP_PHONE;
case Manifest.permission.BODY_SENSORS:
return PermissionConstants.PERMISSION_GROUP_SENSORS;
......@@ -154,9 +155,8 @@ public class PermissionUtils {
if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_PHONE_STATE))
permissionNames.add(Manifest.permission.READ_PHONE_STATE);
if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.Q && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_PHONE_NUMBERS)) {
if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.Q && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_PHONE_NUMBERS))
permissionNames.add(Manifest.permission.READ_PHONE_NUMBERS);
}
if (hasPermissionInManifest(context, permissionNames, Manifest.permission.CALL_PHONE))
permissionNames.add(Manifest.permission.CALL_PHONE);
......@@ -173,9 +173,6 @@ public class PermissionUtils {
if (hasPermissionInManifest(context, permissionNames, Manifest.permission.USE_SIP))
permissionNames.add(Manifest.permission.USE_SIP);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && hasPermissionInManifest(context, permissionNames, Manifest.permission.BIND_CALL_REDIRECTION_SERVICE))
permissionNames.add(Manifest.permission.BIND_CALL_REDIRECTION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasPermissionInManifest(context, permissionNames, Manifest.permission.ANSWER_PHONE_CALLS))
permissionNames.add(Manifest.permission.ANSWER_PHONE_CALLS);
......@@ -458,6 +455,32 @@ public class PermissionUtils {
return PermissionConstants.PERMISSION_STATUS_GRANTED;
}
@NonNull
@PermissionConstants.PermissionStatus
static Integer strictestStatus(final @NonNull Collection<@PermissionConstants.PermissionStatus Integer> statuses) {
if (statuses.contains(PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN))
return PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN;
if (statuses.contains(PermissionConstants.PERMISSION_STATUS_RESTRICTED))
return PermissionConstants.PERMISSION_STATUS_RESTRICTED;
if (statuses.contains(PermissionConstants.PERMISSION_STATUS_DENIED))
return PermissionConstants.PERMISSION_STATUS_DENIED;
if (statuses.contains(PermissionConstants.PERMISSION_STATUS_LIMITED))
return PermissionConstants.PERMISSION_STATUS_LIMITED;
return PermissionConstants.PERMISSION_STATUS_GRANTED;
}
@NonNull
@PermissionConstants.PermissionStatus
static Integer strictestStatus(
final @Nullable @PermissionConstants.PermissionStatus Integer statusA,
final @Nullable @PermissionConstants.PermissionStatus Integer statusB) {
final Collection<@PermissionConstants.PermissionStatus Integer> statuses = new HashSet<>();
statuses.add(statusA);
statuses.add(statusB);
return strictestStatus(statuses);
}
/**
* Determines whether a permission was either 'denied' or 'permanently denied'.
* <p>
......
......@@ -37,7 +37,6 @@
<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.BIND_CALL_REDIRECTION_SERVICE"/>
<!-- Permissions options for the `calendar` group -->
<uses-permission android:name="android.permission.READ_CALENDAR" />
......
name: permission_handler_android
description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions.
homepage: https://github.com/baseflow/flutter-permission-handler
version: 11.0.1
version: 11.0.2
environment:
sdk: ">=2.15.0 <4.0.0"
......
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