Commit c2548020 by Maurits van Beusekom

Production release 4.2.0

parents d5d6ef23 ed133b68
## 4.2.0
* Android: Methods `checkPermissionStatus` and `requestPermissions` now support addition `neverAskAgain` status.
## 4.1.0
* iOS: Added option to exclude permissions logic using macros. This allows developers to submit their app to the AppStore without having to include all permissions in their Info.plist;
......
......@@ -22,7 +22,7 @@ To use this plugin, add `permission_handler` as a [dependency in your pubspec.ya
```yaml
dependencies:
permission_handler: '^4.1.0'
permission_handler: '^4.2.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).
......@@ -277,6 +277,9 @@ enum PermissionStatus {
/// Permission is in an unknown state
unknown
/// Permission to access the requested feature is denied by the user and never show selected (only on Android).
neverAskAgain
}
```
......
......@@ -19,6 +19,7 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationManagerCompat;
import io.flutter.plugin.common.PluginRegistry.ActivityResultListener;
import java.lang.annotation.Retention;
......@@ -100,7 +101,7 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
private static final int PERMISSION_STATUS_GRANTED = 2;
private static final int PERMISSION_STATUS_RESTRICTED = 3;
private static final int PERMISSION_STATUS_UNKNOWN = 4;
private static final int PERMISSION_STATUS_NEWER_ASK_AGAIN = 5;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
PERMISSION_STATUS_DENIED,
......@@ -108,6 +109,7 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
PERMISSION_STATUS_GRANTED,
PERMISSION_STATUS_RESTRICTED,
PERMISSION_STATUS_UNKNOWN,
PERMISSION_STATUS_NEWER_ASK_AGAIN,
})
private @interface PermissionStatus {
}
......@@ -302,7 +304,9 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
}
final int permissionStatus = ContextCompat.checkSelfPermission(context, name);
if (permissionStatus == PackageManager.PERMISSION_DENIED) {
return PERMISSION_STATUS_DENIED;
if (VERSION.SDK_INT >= VERSION_CODES.M && isNeverAskAgainSelected(permission)) {
return PERMISSION_STATUS_NEWER_ASK_AGAIN;
} else return PERMISSION_STATUS_DENIED;
} else if (permissionStatus != PackageManager.PERMISSION_GRANTED) {
return PERMISSION_STATUS_UNKNOWN;
}
......@@ -456,21 +460,24 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
if (permission == PERMISSION_GROUP_UNKNOWN)
continue;
final int result = grantResults[i];
updatePermissionShouldShowStatus(permission);
if (permission == PERMISSION_GROUP_MICROPHONE) {
if (!mRequestResults.containsKey(PERMISSION_GROUP_MICROPHONE)) {
mRequestResults.put(PERMISSION_GROUP_MICROPHONE, toPermissionStatus(grantResults[i]));
mRequestResults.put(PERMISSION_GROUP_MICROPHONE, toPermissionStatus(permission, result));
}
if (!mRequestResults.containsKey(PERMISSION_GROUP_SPEECH)) {
mRequestResults.put(PERMISSION_GROUP_SPEECH, toPermissionStatus(grantResults[i]));
mRequestResults.put(PERMISSION_GROUP_SPEECH, toPermissionStatus(permission, result));
}
} else if (permission == PERMISSION_GROUP_LOCATION_ALWAYS) {
@PermissionStatus int permissionStatus = determineActualLocationStatus(grantResults[i]);
@PermissionStatus int permissionStatus = determineActualLocationStatus(permission, result);
if (!mRequestResults.containsKey(PERMISSION_GROUP_LOCATION_ALWAYS)) {
mRequestResults.put(PERMISSION_GROUP_LOCATION_ALWAYS, permissionStatus);
}
} else if (permission == PERMISSION_GROUP_LOCATION) {
@PermissionStatus int permissionStatus = determineActualLocationStatus(grantResults[i]);
@PermissionStatus int permissionStatus = determineActualLocationStatus(permission, result);
if (VERSION.SDK_INT < VERSION_CODES.Q) {
if (!mRequestResults.containsKey(PERMISSION_GROUP_LOCATION_ALWAYS)) {
......@@ -484,7 +491,7 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
mRequestResults.put(permission, permissionStatus);
} else if (!mRequestResults.containsKey(permission)) {
mRequestResults.put(permission, toPermissionStatus(grantResults[i]));
mRequestResults.put(permission, toPermissionStatus(permission, result));
}
}
......@@ -497,11 +504,11 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
* @param grantResult Grant Result as received from the Android system.
*/
@PermissionStatus
private int determineActualLocationStatus(int grantResult) {
private int determineActualLocationStatus(@PermissionGroup int permission, int grantResult) {
final Context context =
mRegistrar.activity() == null ? mRegistrar.activeContext() : mRegistrar.activity();
final boolean isLocationServiceEnabled = context != null && isLocationServiceEnabled(context);
@PermissionStatus int permissionStatus = toPermissionStatus(grantResult);
@PermissionStatus int permissionStatus = toPermissionStatus(permission, grantResult);
if (permissionStatus == PERMISSION_STATUS_GRANTED && !isLocationServiceEnabled) {
permissionStatus = PERMISSION_STATUS_DISABLED;
}
......@@ -521,7 +528,11 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
}
@PermissionStatus
private int toPermissionStatus(int grantResult) {
private int toPermissionStatus(@PermissionGroup int permission, int grantResult) {
if (VERSION.SDK_INT >= VERSION_CODES.M && isNeverAskAgainSelected(permission)) {
return PERMISSION_STATUS_NEWER_ASK_AGAIN;
}
return grantResult == PackageManager.PERMISSION_GRANTED ? PERMISSION_STATUS_GRANTED : PERMISSION_STATUS_DENIED;
}
......@@ -722,6 +733,46 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
return false;
}
private void updatePermissionShouldShowStatus(@PermissionGroup int permission) {
List<String> names = getManifestNames(permission);
if (names == null || names.isEmpty()) {
return;
}
final Context context = mRegistrar.activity() == null ? mRegistrar.activeContext() : mRegistrar.activity();
if (context == null) {
return;
}
for (String name : names) {
PermissionUtils.setRequestedPermission(context, name);
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private boolean isNeverAskAgainSelected(@PermissionGroup int permission) {
List<String> names = getManifestNames(permission);
if (names == null || names.isEmpty()) {
return false;
}
final Activity activity = mRegistrar.activity();
if (activity == null) {
return false;
}
boolean isNeverAskAgainSelected = false;
for (String name : names) {
isNeverAskAgainSelected |= PermissionUtils.neverAskAgainSelected(activity, name);
}
return isNeverAskAgainSelected;
}
@SuppressWarnings("deprecation")
private boolean isLocationServiceEnabled(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
......
package com.baseflow.permissionhandler;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
public class PermissionUtils {
@RequiresApi(api = Build.VERSION_CODES.M)
static boolean neverAskAgainSelected(final Activity activity, final String permission) {
final boolean hasRequestedPermissionBefore = getRequestedPermissionBefore(activity, permission);
final boolean shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
return hasRequestedPermissionBefore != shouldShowRequestPermissionRationale;
}
static void setRequestedPermission(final Context context, final String permission) {
SharedPreferences genPrefs = context.getSharedPreferences("GENERIC_PREFERENCES", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = genPrefs.edit();
editor.putBoolean(permission, true);
editor.apply();
}
private static boolean getRequestedPermissionBefore(final Context context, final String permission) {
SharedPreferences genPrefs = context.getSharedPreferences("GENERIC_PREFERENCES", Context.MODE_PRIVATE);
return genPrefs.getBoolean(permission, false);
}
}
......@@ -3,7 +3,7 @@
#
Pod::Spec.new do |s|
s.name = 'permission_handler'
s.version = '4.1.0'
s.version = '4.2.0'
s.summary = 'Permission plugin for Flutter.'
s.description = <<-DESC
Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
......
......@@ -21,12 +21,16 @@ class PermissionStatus {
/// Permission is in an unknown state
static const PermissionStatus unknown = PermissionStatus._(4);
/// Permission to access the requested feature is denied by the user and never show selected (only on Android).
static const PermissionStatus neverAskAgain = PermissionStatus._(5);
static const List<PermissionStatus> values = <PermissionStatus>[
denied,
disabled,
granted,
restricted,
unknown,
neverAskAgain,
];
static const List<String> _names = <String>[
......@@ -35,6 +39,7 @@ class PermissionStatus {
'granted',
'restricted',
'unknown',
'neverAskAgain',
];
@override
......
name: permission_handler
description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
version: 4.1.0
version: 4.2.0
homepage: https://github.com/baseflowit/flutter-permission-handler
environment:
......
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