Commit 681bc4ca by Maurits van Beusekom Committed by GitHub

Merge pull request #526 from Baseflow/scoped_storage_permission

Added MANAGE_EXTERNAL_STORAGE permission
parents 14368466 70e32f8f
## 7.0.0
This release contains the following **breaking changes**:
* Updated compile SDK version to 30 in the build.gradle for handling the MANAGE_EXTERNAL_STORAGE permission;
* Added the MANAGE_EXTERNAL_STORAGE permission for Android R and up;
* Registered listeners on the plugin level to prevent memory leaks or unwanted behaviour.
## 6.1.3
* Implement equality operator on the `Permission` class;
......
......@@ -28,7 +28,7 @@ project.getTasks().withType(JavaCompile){
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
compileSdkVersion 30
defaultConfig {
minSdkVersion 16
......
......@@ -6,12 +6,9 @@ import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result;
import com.baseflow.permissionhandler.PermissionManager.ActivityRegistry;
import com.baseflow.permissionhandler.PermissionManager.PermissionRegistry;
import java.util.List;
......@@ -35,26 +32,10 @@ final class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
@Nullable
private Activity activity;
@Nullable
private ActivityRegistry activityRegistry;
@Nullable
private PermissionRegistry permissionRegistry;
public void setActivity(@Nullable Activity activity) {
this.activity = activity;
}
public void setActivityRegistry(
@Nullable ActivityRegistry activityRegistry) {
this.activityRegistry = activityRegistry;
}
public void setPermissionRegistry(
@Nullable PermissionRegistry permissionRegistry) {
this.permissionRegistry = permissionRegistry;
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result)
{
......@@ -91,8 +72,6 @@ final class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
permissionManager.requestPermissions(
permissions,
activity,
activityRegistry,
permissionRegistry,
result::success,
(String errorCode, String errorDescription) -> result.error(
errorCode,
......
......@@ -8,7 +8,8 @@ import java.lang.annotation.RetentionPolicy;
final class PermissionConstants {
static final String LOG_TAG = "permissions_handler";
static final int PERMISSION_CODE = 24;
static final int PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS = 5672353;
static final int PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS = 209;
static final int PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE = 210;
//PERMISSION_GROUP
static final int PERMISSION_GROUP_CALENDAR = 0;
......@@ -33,6 +34,7 @@ final class PermissionConstants {
static final int PERMISSION_GROUP_ACTIVITY_RECOGNITION = 19;
static final int PERMISSION_GROUP_UNKNOWN = 20;
static final int PERMISSION_GROUP_BLUETOOTH = 21;
static final int PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE = 22;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
......@@ -57,6 +59,7 @@ final class PermissionConstants {
PERMISSION_GROUP_ACTIVITY_RECOGNITION,
PERMISSION_GROUP_UNKNOWN,
PERMISSION_GROUP_BLUETOOTH,
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
})
@interface PermissionGroup {
}
......@@ -74,7 +77,7 @@ final class PermissionConstants {
PERMISSION_STATUS_GRANTED,
PERMISSION_STATUS_RESTRICTED,
PERMISSION_STATUS_LIMITED,
PERMISSION_STATUS_NEVER_ASK_AGAIN,
PERMISSION_STATUS_NEVER_ASK_AGAIN
})
@interface PermissionStatus {
}
......
......@@ -4,8 +4,6 @@ import android.app.Activity;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.baseflow.permissionhandler.PermissionManager.ActivityRegistry;
import com.baseflow.permissionhandler.PermissionManager.PermissionRegistry;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
......@@ -23,11 +21,21 @@ import io.flutter.plugin.common.MethodChannel;
*/
public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAware {
private final PermissionManager permissionManager;
private MethodChannel methodChannel;
@SuppressWarnings("deprecation")
@Nullable private io.flutter.plugin.common.PluginRegistry.Registrar pluginRegistrar;
@Nullable private ActivityPluginBinding pluginBinding;
@Nullable
private MethodCallHandlerImpl methodCallHandler;
public PermissionHandlerPlugin() {
this.permissionManager = new PermissionManager();
}
/**
* Registers a plugin implementation that uses the stable {@code io.flutter.plugin.common}
* package.
......@@ -38,13 +46,15 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
@SuppressWarnings("deprecation")
public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) {
final PermissionHandlerPlugin plugin = new PermissionHandlerPlugin();
plugin.pluginRegistrar = registrar;
plugin.registerListeners();
plugin.startListening(registrar.context(), registrar.messenger());
if (registrar.activeContext() instanceof Activity) {
plugin.startListeningToActivity(
registrar.activity(),
registrar::addActivityResultListener,
registrar::addRequestPermissionsResultListener
registrar.activity()
);
}
}
......@@ -65,10 +75,11 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
startListeningToActivity(
binding.getActivity(),
binding::addActivityResultListener,
binding::addRequestPermissionsResultListener
binding.getActivity()
);
this.pluginBinding = binding;
registerListeners();
}
@Override
......@@ -79,6 +90,8 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
@Override
public void onDetachedFromActivity() {
stopListeningToActivity();
deregisterListeners();
}
@Override
......@@ -95,7 +108,7 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
methodCallHandler = new MethodCallHandlerImpl(
applicationContext,
new AppSettingsManager(),
new PermissionManager(),
this.permissionManager,
new ServiceManager()
);
......@@ -109,22 +122,33 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
}
private void startListeningToActivity(
Activity activity,
ActivityRegistry activityRegistry,
PermissionRegistry permissionRegistry
Activity activity
) {
if (methodCallHandler != null) {
methodCallHandler.setActivity(activity);
methodCallHandler.setActivityRegistry(activityRegistry);
methodCallHandler.setPermissionRegistry(permissionRegistry);
}
}
private void stopListeningToActivity() {
if (methodCallHandler != null) {
methodCallHandler.setActivity(null);
methodCallHandler.setActivityRegistry(null);
methodCallHandler.setPermissionRegistry(null);
}
}
private void registerListeners() {
if (this.pluginRegistrar != null) {
this.pluginRegistrar.addActivityResultListener(this.permissionManager);
this.pluginRegistrar.addRequestPermissionsResultListener(this.permissionManager);
} else if (pluginBinding != null) {
this.pluginBinding.addActivityResultListener(this.permissionManager);
this.pluginBinding.addRequestPermissionsResultListener(this.permissionManager);
}
}
private void deregisterListeners() {
if (this.pluginBinding != null) {
this.pluginBinding.removeActivityResultListener(this.permissionManager);
this.pluginBinding.removeRequestPermissionsResultListener(this.permissionManager);
}
}
}
......@@ -6,6 +6,7 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import androidx.annotation.RequiresApi;
......@@ -60,6 +61,8 @@ public class PermissionUtils {
return PermissionConstants.PERMISSION_GROUP_ACCESS_MEDIA_LOCATION;
case Manifest.permission.ACTIVITY_RECOGNITION:
return PermissionConstants.PERMISSION_GROUP_ACTIVITY_RECOGNITION;
case Manifest.permission.MANAGE_EXTERNAL_STORAGE:
return PermissionConstants.PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE;
default:
return PermissionConstants.PERMISSION_GROUP_UNKNOWN;
}
......@@ -177,8 +180,11 @@ public class PermissionUtils {
if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_EXTERNAL_STORAGE))
permissionNames.add(Manifest.permission.READ_EXTERNAL_STORAGE);
if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_EXTERNAL_STORAGE))
permissionNames.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && Environment.isExternalStorageLegacy())) {
if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_EXTERNAL_STORAGE))
permissionNames.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
break;
}
break;
case PermissionConstants.PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS:
......@@ -197,7 +203,7 @@ public class PermissionUtils {
break;
case PermissionConstants.PERMISSION_GROUP_ACTIVITY_RECOGNITION:
// The ACCESS_MEDIA_LOCATION permission is introduced in Android Q, meaning we should
// The ACTIVITY_RECOGNITION permission is introduced in Android Q, meaning we should
// not handle permissions on pre Android Q devices.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
return null;
......@@ -210,6 +216,14 @@ public class PermissionUtils {
if (hasPermissionInManifest(context, permissionNames, Manifest.permission.BLUETOOTH))
permissionNames.add(Manifest.permission.BLUETOOTH);
break;
case PermissionConstants.PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE:
// The MANAGE_EXTERNAL_STORAGE permission is introduced in Android R, meaning we should
// not handle permissions on pre Android R devices.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && hasPermissionInManifest(context, permissionNames, Manifest.permission.MANAGE_EXTERNAL_STORAGE ))
permissionNames.add(Manifest.permission.MANAGE_EXTERNAL_STORAGE);
break;
case PermissionConstants.PERMISSION_GROUP_NOTIFICATION:
case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY:
case PermissionConstants.PERMISSION_GROUP_PHOTOS:
......
......@@ -25,7 +25,7 @@ apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 29
compileSdkVersion 30
lintOptions {
disable 'InvalidPackage'
......
......@@ -63,6 +63,9 @@
<!-- Permissions options for the `bluetooth` group -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- Permissions options for the `manage external storage` group -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<application
android:name="io.flutter.app.FlutterApplication"
android:icon="@mipmap/ic_launcher"
......
......@@ -20,7 +20,8 @@ class PermissionList extends StatelessWidget {
permission != Permission.storage &&
permission != Permission.ignoreBatteryOptimizations &&
permission != Permission.accessMediaLocation &&
permission != Permission.activityRecognition;
permission != Permission.activityRecognition &&
permission != Permission.manageExternalStorage;
} else {
return permission != Permission.unknown &&
permission != Permission.mediaLibrary &&
......
......@@ -118,6 +118,7 @@ typedef NS_ENUM(int, PermissionGroup) {
PermissionGroupActivityRecognition,
PermissionGroupUnknown,
PermissionGroupBluetooth,
PermissionGroupManageExternalStorage
};
typedef NS_ENUM(int, PermissionStatus) {
......
name: permission_handler
description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
version: 6.1.3
version: 7.0.0
homepage: https://github.com/baseflowit/flutter-permission-handler
flutter:
......@@ -16,7 +16,7 @@ dependencies:
flutter:
sdk: flutter
meta: ^1.3.0
permission_handler_platform_interface: ^3.1.3
permission_handler_platform_interface: ^3.2.0
dev_dependencies:
flutter_test:
......
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