Commit 11055f41 by Jeroen Weener Committed by GitHub

Return 'permanently denied' as permission status (#1130)

* Return 'permanently denied' as status when appropriate

* Make `checkPermissionStatus` callable from background

* Update version number

* Make use of `Activity` more explicit

* Format java code

* Refactor activity and context bookkeeping

* Initialize `PermissionManager` in `onAttachedToEngine`

* Follow-up from merge
parent 921652cd
## 11.0.0
* **BREAKING CHANGE:** Fixes a bug where the permission status would return 'denied' regardless of whether the status was 'denied' or 'permanently denied'.
## 10.3.6 ## 10.3.6
* Fixes a bug where requesting multiple permissions would crash the app if at least one of the permissions was a [special permission](https://developer.android.com/guide/topics/permissions/overview#special). * Fixes a bug where requesting multiple permissions would crash the app if at least one of the permissions was a [special permission](https://developer.android.com/guide/topics/permissions/overview#special).
......
package com.baseflow.permissionhandler; package com.baseflow.permissionhandler;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.MethodChannel.Result;
...@@ -19,81 +17,70 @@ final class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { ...@@ -19,81 +17,70 @@ final class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
private final ServiceManager serviceManager; private final ServiceManager serviceManager;
MethodCallHandlerImpl( MethodCallHandlerImpl(
Context applicationContext, Context applicationContext,
AppSettingsManager appSettingsManager, AppSettingsManager appSettingsManager,
PermissionManager permissionManager, PermissionManager permissionManager,
ServiceManager serviceManager) { ServiceManager serviceManager) {
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
this.appSettingsManager = appSettingsManager; this.appSettingsManager = appSettingsManager;
this.permissionManager = permissionManager; this.permissionManager = permissionManager;
this.serviceManager = serviceManager; this.serviceManager = serviceManager;
} }
@Nullable @Override
private Activity activity; public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) {
public void setActivity(@Nullable Activity activity) {
this.activity = activity;
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result)
{
switch (call.method) { switch (call.method) {
case "checkServiceStatus": { case "checkServiceStatus": {
@PermissionConstants.PermissionGroup final int permission = Integer.parseInt(call.arguments.toString()); @PermissionConstants.PermissionGroup final int permission = Integer.parseInt(call.arguments.toString());
serviceManager.checkServiceStatus( serviceManager.checkServiceStatus(
permission, permission,
applicationContext, applicationContext,
result::success, result::success,
(String errorCode, String errorDescription) -> result.error( (String errorCode, String errorDescription) -> result.error(
errorCode, errorCode,
errorDescription, errorDescription,
null)); null));
break; break;
} }
case "checkPermissionStatus": { case "checkPermissionStatus": {
@PermissionConstants.PermissionGroup final int permission = Integer.parseInt(call.arguments.toString()); @PermissionConstants.PermissionGroup final int permission = Integer.parseInt(call.arguments.toString());
permissionManager.checkPermissionStatus( permissionManager.checkPermissionStatus(
permission, permission,
applicationContext, result::success);
result::success);
break; break;
} }
case "requestPermissions": case "requestPermissions":
final List<Integer> permissions = call.arguments(); final List<Integer> permissions = call.arguments();
permissionManager.requestPermissions( permissionManager.requestPermissions(
permissions, permissions,
activity, result::success,
result::success, (String errorCode, String errorDescription) -> result.error(
(String errorCode, String errorDescription) -> result.error( errorCode,
errorCode, errorDescription,
errorDescription, null));
null));
break; break;
case "shouldShowRequestPermissionRationale": { case "shouldShowRequestPermissionRationale": {
@PermissionConstants.PermissionGroup final int permission = Integer.parseInt(call.arguments.toString()); @PermissionConstants.PermissionGroup final int permission = Integer.parseInt(call.arguments.toString());
permissionManager.shouldShowRequestPermissionRationale( permissionManager.shouldShowRequestPermissionRationale(
permission, permission,
activity, result::success,
result::success, (String errorCode, String errorDescription) -> result.error(
(String errorCode, String errorDescription) -> result.error( errorCode,
errorCode, errorDescription,
errorDescription, null));
null));
break; break;
} }
case "openAppSettings": case "openAppSettings":
appSettingsManager.openAppSettings( appSettingsManager.openAppSettings(
applicationContext, applicationContext,
result::success, result::success,
(String errorCode, String errorDescription) -> result.error( (String errorCode, String errorDescription) -> result.error(
errorCode, errorCode,
errorDescription, errorDescription,
null)); null));
break; break;
default: default:
......
...@@ -13,7 +13,7 @@ import io.flutter.plugin.common.MethodChannel; ...@@ -13,7 +13,7 @@ import io.flutter.plugin.common.MethodChannel;
/** /**
* Platform implementation of the permission_handler Flutter plugin. * Platform implementation of the permission_handler Flutter plugin.
* *
* <p>Instantiate this in an add to app scenario to gracefully handle activity and context changes. * <p>Instantiate this in an add-to-app scenario to gracefully handle activity and context changes.
* See {@code com.example.permissionhandlerexample.MainActivity} for an example. * See {@code com.example.permissionhandlerexample.MainActivity} for an example.
* *
* <p>Call {@link #registerWith(io.flutter.plugin.common.PluginRegistry.Registrar)} to register an * <p>Call {@link #registerWith(io.flutter.plugin.common.PluginRegistry.Registrar)} to register an
...@@ -21,7 +21,8 @@ import io.flutter.plugin.common.MethodChannel; ...@@ -21,7 +21,8 @@ import io.flutter.plugin.common.MethodChannel;
*/ */
public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAware { public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAware {
private final PermissionManager permissionManager; private PermissionManager permissionManager;
private MethodChannel methodChannel; private MethodChannel methodChannel;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
...@@ -32,10 +33,6 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa ...@@ -32,10 +33,6 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
@Nullable @Nullable
private MethodCallHandlerImpl methodCallHandler; private MethodCallHandlerImpl methodCallHandler;
public PermissionHandlerPlugin() {
this.permissionManager = new PermissionManager();
}
/** /**
* Registers a plugin implementation that uses the stable {@code io.flutter.plugin.common} * Registers a plugin implementation that uses the stable {@code io.flutter.plugin.common}
* package. * package.
...@@ -48,6 +45,7 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa ...@@ -48,6 +45,7 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
final PermissionHandlerPlugin plugin = new PermissionHandlerPlugin(); final PermissionHandlerPlugin plugin = new PermissionHandlerPlugin();
plugin.pluginRegistrar = registrar; plugin.pluginRegistrar = registrar;
plugin.permissionManager = new PermissionManager(registrar.context());
plugin.registerListeners(); plugin.registerListeners();
plugin.startListening(registrar.context(), registrar.messenger()); plugin.startListening(registrar.context(), registrar.messenger());
...@@ -61,6 +59,8 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa ...@@ -61,6 +59,8 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
@Override @Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
this.permissionManager = new PermissionManager(binding.getApplicationContext());
startListening( startListening(
binding.getApplicationContext(), binding.getApplicationContext(),
binding.getBinaryMessenger() binding.getBinaryMessenger()
...@@ -124,14 +124,14 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa ...@@ -124,14 +124,14 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
private void startListeningToActivity( private void startListeningToActivity(
Activity activity Activity activity
) { ) {
if (methodCallHandler != null) { if (permissionManager != null) {
methodCallHandler.setActivity(activity); permissionManager.setActivity(activity);
} }
} }
private void stopListeningToActivity() { private void stopListeningToActivity() {
if (methodCallHandler != null) { if (permissionManager != null) {
methodCallHandler.setActivity(null); permissionManager.setActivity(null);
} }
} }
......
...@@ -36,10 +36,13 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -36,10 +36,13 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
@Nullable @Nullable
private Activity activity; private Activity activity;
@NonNull
private final Context context;
/** /**
* The number of pending permission requests. * The number of pending permission requests.
* <p> * <p>
* This number is set by {@link this#requestPermissions(List, Activity, RequestPermissionsSuccessCallback, ErrorCallback)} * This number is set by {@link this#requestPermissions(List, RequestPermissionsSuccessCallback, ErrorCallback)}
* and then reduced when receiving results in {@link this#onActivityResult(int, int, Intent)} * and then reduced when receiving results in {@link this#onActivityResult(int, int, Intent)}
* and {@link this#onRequestPermissionsResult(int, String[], int[])}. * and {@link this#onRequestPermissionsResult(int, String[], int[])}.
*/ */
...@@ -51,10 +54,18 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -51,10 +54,18 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
* {@link this#onActivityResult(int, int, Intent)} and * {@link this#onActivityResult(int, int, Intent)} and
* {@link this#onRequestPermissionsResult(int, String[], int[])}. * {@link this#onRequestPermissionsResult(int, String[], int[])}.
* It is (re)initialized when new permissions are requested through * It is (re)initialized when new permissions are requested through
* {@link this#requestPermissions(List, Activity, RequestPermissionsSuccessCallback, ErrorCallback)}. * {@link this#requestPermissions(List, RequestPermissionsSuccessCallback, ErrorCallback)}.
*/ */
private Map<Integer, Integer> requestResults; private Map<Integer, Integer> requestResults;
public PermissionManager(@NonNull Context context) {
this.context = context;
}
public void setActivity(@Nullable Activity activity) {
this.activity = activity;
}
@Override @Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) { public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != PermissionConstants.PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS && if (requestCode != PermissionConstants.PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS &&
...@@ -231,14 +242,22 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -231,14 +242,22 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
void onSuccess(boolean shouldShowRequestPermissionRationale); void onSuccess(boolean shouldShowRequestPermissionRationale);
} }
/**
* Determines the permission status of the provided permission.
* <p>
* To distinguish between a status of 'denied' and a status of 'permanently denied', the plugin
* needs access to an activity. If `this.activity` is null, for example when running the
* application in the background, the resolved status will be 'denied' for both 'denied' and
* 'permanently denied'.
*
* @param permission the permission for which to determine the status.
* @param successCallback the callback to which the resolved status must be supplied.
*/
void checkPermissionStatus( void checkPermissionStatus(
@PermissionConstants.PermissionGroup int permission, final @PermissionConstants.PermissionGroup int permission,
Context context, final CheckPermissionsSuccessCallback successCallback) {
CheckPermissionsSuccessCallback successCallback) {
successCallback.onSuccess(determinePermissionStatus( successCallback.onSuccess(determinePermissionStatus(permission));
permission,
context));
} }
/** /**
...@@ -265,13 +284,11 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -265,13 +284,11 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
* requested through this method were handled, and if so, return the result back to Dart. * requested through this method were handled, and if so, return the result back to Dart.
* *
* @param permissions the permissions that are requested. * @param permissions the permissions that are requested.
* @param activity the activity.
* @param successCallback the callback for returning the permission results. * @param successCallback the callback for returning the permission results.
* @param errorCallback the callback to call in case of an error. * @param errorCallback the callback to call in case of an error.
*/ */
void requestPermissions( void requestPermissions(
List<Integer> permissions, List<Integer> permissions,
Activity activity,
RequestPermissionsSuccessCallback successCallback, RequestPermissionsSuccessCallback successCallback,
ErrorCallback errorCallback) { ErrorCallback errorCallback) {
if (pendingRequestCount > 0) { if (pendingRequestCount > 0) {
...@@ -291,13 +308,12 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -291,13 +308,12 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
} }
this.successCallback = successCallback; this.successCallback = successCallback;
this.activity = activity;
this.requestResults = new HashMap<>(); this.requestResults = new HashMap<>();
this.pendingRequestCount = 0; // sanity check this.pendingRequestCount = 0; // sanity check
ArrayList<String> permissionsToRequest = new ArrayList<>(); ArrayList<String> permissionsToRequest = new ArrayList<>();
for (Integer permission : permissions) { for (Integer permission : permissions) {
@PermissionConstants.PermissionStatus final int permissionStatus = determinePermissionStatus(permission, activity); @PermissionConstants.PermissionStatus final int permissionStatus = determinePermissionStatus(permission);
if (permissionStatus == PermissionConstants.PERMISSION_STATUS_GRANTED) { if (permissionStatus == PermissionConstants.PERMISSION_STATUS_GRANTED) {
if (!requestResults.containsKey(permission)) { if (!requestResults.containsKey(permission)) {
requestResults.put(permission, PermissionConstants.PERMISSION_STATUS_GRANTED); requestResults.put(permission, PermissionConstants.PERMISSION_STATUS_GRANTED);
...@@ -377,23 +393,21 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -377,23 +393,21 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
} }
@PermissionConstants.PermissionStatus @PermissionConstants.PermissionStatus
private int determinePermissionStatus( private int determinePermissionStatus(final @PermissionConstants.PermissionGroup int permission) {
@PermissionConstants.PermissionGroup int permission,
Context context) {
if (permission == PermissionConstants.PERMISSION_GROUP_NOTIFICATION) { if (permission == PermissionConstants.PERMISSION_GROUP_NOTIFICATION) {
return checkNotificationPermissionStatus(context); return checkNotificationPermissionStatus();
} }
if (permission == PermissionConstants.PERMISSION_GROUP_BLUETOOTH) { if (permission == PermissionConstants.PERMISSION_GROUP_BLUETOOTH) {
return checkBluetoothPermissionStatus(context); return checkBluetoothPermissionStatus();
} }
if (permission == PermissionConstants.PERMISSION_GROUP_BLUETOOTH_CONNECT if (permission == PermissionConstants.PERMISSION_GROUP_BLUETOOTH_CONNECT
|| permission == PermissionConstants.PERMISSION_GROUP_BLUETOOTH_SCAN || permission == PermissionConstants.PERMISSION_GROUP_BLUETOOTH_SCAN
|| permission == PermissionConstants.PERMISSION_GROUP_BLUETOOTH_ADVERTISE) { || permission == PermissionConstants.PERMISSION_GROUP_BLUETOOTH_ADVERTISE) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
return checkBluetoothPermissionStatus(context); return checkBluetoothPermissionStatus();
} }
} }
...@@ -498,7 +512,7 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -498,7 +512,7 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
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 PermissionUtils.determineDeniedVariant(activity, name);
} }
} }
} }
...@@ -527,7 +541,6 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -527,7 +541,6 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
void shouldShowRequestPermissionRationale( void shouldShowRequestPermissionRationale(
int permission, int permission,
Activity activity,
ShouldShowRequestPermissionRationaleSuccessCallback successCallback, ShouldShowRequestPermissionRationaleSuccessCallback successCallback,
ErrorCallback errorCallback) { ErrorCallback errorCallback) {
if (activity == null) { if (activity == null) {
...@@ -557,22 +570,26 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, ...@@ -557,22 +570,26 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener,
successCallback.onSuccess(ActivityCompat.shouldShowRequestPermissionRationale(activity, names.get(0))); successCallback.onSuccess(ActivityCompat.shouldShowRequestPermissionRationale(activity, names.get(0)));
} }
private int checkNotificationPermissionStatus(Context context) { @PermissionConstants.PermissionStatus
private int checkNotificationPermissionStatus() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
NotificationManagerCompat manager = NotificationManagerCompat.from(context); NotificationManagerCompat manager = NotificationManagerCompat.from(context);
boolean isGranted = manager.areNotificationsEnabled(); final boolean isGranted = manager.areNotificationsEnabled();
if (isGranted) { if (isGranted) {
return PermissionConstants.PERMISSION_STATUS_GRANTED; return PermissionConstants.PERMISSION_STATUS_GRANTED;
} }
return PermissionConstants.PERMISSION_STATUS_DENIED; return PermissionConstants.PERMISSION_STATUS_DENIED;
} }
return context.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED final int status = context.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS);
? PermissionConstants.PERMISSION_STATUS_GRANTED if (status == PackageManager.PERMISSION_GRANTED) {
: PermissionConstants.PERMISSION_STATUS_DENIED; return PermissionConstants.PERMISSION_STATUS_GRANTED;
}
return PermissionConstants.PERMISSION_STATUS_DENIED;
} }
private int checkBluetoothPermissionStatus(Context context) { @PermissionConstants.PermissionStatus
private int checkBluetoothPermissionStatus() {
List<String> names = PermissionUtils.getManifestNames(context, PermissionConstants.PERMISSION_GROUP_BLUETOOTH); List<String> names = PermissionUtils.getManifestNames(context, PermissionConstants.PERMISSION_GROUP_BLUETOOTH);
boolean missingInManifest = names == null || names.isEmpty(); boolean missingInManifest = names == null || names.isEmpty();
if (missingInManifest) { if (missingInManifest) {
......
...@@ -10,6 +10,8 @@ import android.os.Build; ...@@ -10,6 +10,8 @@ import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
...@@ -437,39 +439,70 @@ public class PermissionUtils { ...@@ -437,39 +439,70 @@ public class PermissionUtils {
* *
* @param activity the activity for context * @param activity the activity for context
* @param permissionName the name of the permission * @param permissionName the name of the permission
* @param grantResult the result of the permission intent * @param grantResult the result of the permission intent. Either
* {@link PackageManager#PERMISSION_DENIED} or {@link PackageManager#PERMISSION_GRANTED}.
* @return {@link PermissionConstants#PERMISSION_STATUS_GRANTED}, * @return {@link PermissionConstants#PERMISSION_STATUS_GRANTED},
* {@link PermissionConstants#PERMISSION_STATUS_DENIED}, or * {@link PermissionConstants#PERMISSION_STATUS_DENIED}, or
* {@link PermissionConstants#PERMISSION_STATUS_NEVER_ASK_AGAIN}. * {@link PermissionConstants#PERMISSION_STATUS_NEVER_ASK_AGAIN}.
*/ */
@PermissionConstants.PermissionStatus @PermissionConstants.PermissionStatus
static int toPermissionStatus(final Activity activity, final String permissionName, int grantResult) { static int toPermissionStatus(
if (grantResult == PackageManager.PERMISSION_DENIED) { final @Nullable Activity activity,
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { final String permissionName,
return PermissionConstants.PERMISSION_STATUS_DENIED; int grantResult) {
}
final boolean wasDeniedBefore = PermissionUtils.wasPermissionDeniedBefore(activity, permissionName); if (grantResult == PackageManager.PERMISSION_DENIED) {
final boolean shouldShowRational = !PermissionUtils.isNeverAskAgainSelected(activity, permissionName); return determineDeniedVariant(activity, permissionName);
}
//noinspection SimplifiableConditionalExpression return PermissionConstants.PERMISSION_STATUS_GRANTED;
final boolean isDenied = wasDeniedBefore ? !shouldShowRational : shouldShowRational; }
if (!wasDeniedBefore && isDenied) { /**
setPermissionDenied(activity, permissionName); * Determines whether a permission was either 'denied' or 'permanently denied'.
} * <p>
* To distinguish between these two variants, the method needs access to an {@link Activity}.
* If the provided activity is null, the result will always be resolved to 'denied'.
*
* @param activity the activity needed to resolve the permission status.
* @param permissionName the name of the permission.
* @return either {@link PermissionConstants#PERMISSION_STATUS_DENIED} or
* {@link PermissionConstants#PERMISSION_STATUS_NEVER_ASK_AGAIN}.
*/
@PermissionConstants.PermissionStatus
static int determineDeniedVariant(
final @Nullable Activity activity,
final String permissionName) {
if (wasDeniedBefore && isDenied) { if (activity == null) {
return PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN; return PermissionConstants.PERMISSION_STATUS_DENIED;
} }
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return PermissionConstants.PERMISSION_STATUS_DENIED; return PermissionConstants.PERMISSION_STATUS_DENIED;
} }
return PermissionConstants.PERMISSION_STATUS_GRANTED; final boolean wasDeniedBefore = PermissionUtils.wasPermissionDeniedBefore(activity, permissionName);
final boolean shouldShowRational = !PermissionUtils.isNeverAskAgainSelected(activity, permissionName);
//noinspection SimplifiableConditionalExpression
final boolean isDenied = wasDeniedBefore ? !shouldShowRational : shouldShowRational;
if (!wasDeniedBefore && isDenied) {
setPermissionDenied(activity, permissionName);
}
if (wasDeniedBefore && isDenied) {
return PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN;
}
return PermissionConstants.PERMISSION_STATUS_DENIED;
} }
static void updatePermissionShouldShowStatus(final Activity activity, @PermissionConstants.PermissionGroup int permission) { static void updatePermissionShouldShowStatus(
@Nullable final Activity activity,
@PermissionConstants.PermissionGroup int permission) {
if (activity == null) { if (activity == null) {
return; return;
} }
...@@ -482,10 +515,9 @@ public class PermissionUtils { ...@@ -482,10 +515,9 @@ public class PermissionUtils {
} }
@RequiresApi(api = Build.VERSION_CODES.M) @RequiresApi(api = Build.VERSION_CODES.M)
static boolean isNeverAskAgainSelected(final Activity activity, final String name) { static boolean isNeverAskAgainSelected(
if (activity == null) { @NonNull final Activity activity,
return false; final String name) {
}
final boolean shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity, name); final boolean shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity, name);
return !shouldShowRequestPermissionRationale; return !shouldShowRequestPermissionRationale;
......
name: permission_handler_android name: permission_handler_android
description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions. description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions.
homepage: https://github.com/baseflow/flutter-permission-handler homepage: https://github.com/baseflow/flutter-permission-handler
version: 10.3.6 version: 11.0.0
environment: environment:
sdk: ">=2.15.0 <4.0.0" 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