Commit 24ecfe2a by Maurits van Beusekom

Release 3.2.0

parents bc3e34a5 f63c6c23
## 3.2.0
* Add support for Androids' "ignore battery optimizations" permission;
* Improve error logging;
* Documented support for AndroidX.
## 3.1.0
* Support service status inquiry for phone permission on iOS & Android.
......
......@@ -22,10 +22,29 @@ To use this plugin, add `permission_handler` as a [dependency in your pubspec.ya
```yaml
dependencies:
permission_handler: '^3.1.0'
permission_handler: '^3.2.0'
```
> **NOTE:** There's a known issue with integrating plugins that use Swift into a Flutter project created with the Objective-C template. See issue [Flutter#16049](https://github.com/flutter/flutter/issues/16049) for help on integration.
> **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).
>
>The TL;DR version is:
>
>1. Add the following to your "gradle.properties" file:
>
>```
>android.useAndroidX=true
>android.enableJetifier=true
>```
>2. Make sure you set the `compileSdkVersion` in your "android/app/build.gradle" file to 28:
>
>```
>android {
> compileSdkVersion 28
>
> ...
>}
>```
>3. Make sure you replace all the `android.` dependencies to their AndroidX counterparts (a full list can be found here: https://developer.android.com/jetpack/androidx/migrate).
## API
......
......@@ -11,11 +11,15 @@ import android.content.pm.ResolveInfo;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.PowerManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import io.flutter.plugin.common.PluginRegistry.ActivityResultListener;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
......@@ -37,6 +41,7 @@ import io.flutter.plugin.common.PluginRegistry.Registrar;
public class PermissionHandlerPlugin implements MethodCallHandler {
private static final String LOG_TAG = "permissions_handler";
private static final int PERMISSION_CODE = 24;
private static final int PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS = 5672353;
//PERMISSION_GROUP
private static final int PERMISSION_GROUP_CALENDAR = 0;
......@@ -54,7 +59,8 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
private static final int PERMISSION_GROUP_SMS = 12;
private static final int PERMISSION_GROUP_SPEECH = 13;
private static final int PERMISSION_GROUP_STORAGE = 14;
private static final int PERMISSION_GROUP_UNKNOWN = 15;
private static final int PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS = 15;
private static final int PERMISSION_GROUP_UNKNOWN = 16;
private PermissionHandlerPlugin(Registrar mRegistrar) {
this.mRegistrar = mRegistrar;
......@@ -77,6 +83,7 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
PERMISSION_GROUP_SMS,
PERMISSION_GROUP_SPEECH,
PERMISSION_GROUP_STORAGE,
PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS,
PERMISSION_GROUP_UNKNOWN,
})
private @interface PermissionGroup {
......@@ -133,6 +140,18 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
}
}
});
registrar.addActivityResultListener(new ActivityResultListener() {
@Override
public boolean onActivityResult(int requestCode, int responseCode, Intent intent) {
if (requestCode == PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS) {
permissionHandlerPlugin.handleIgnoreBatteryOptimizationsRequest(responseCode == Activity.RESULT_OK);
return true;
}
return false;
}
});
}
@PermissionGroup
......@@ -232,14 +251,14 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
final List<String> names = getManifestNames(permission);
if (names == null) {
Log.d(LOG_TAG, "No android specific permissions needed for: $permission");
Log.d(LOG_TAG, "No android specific permissions needed for: " + permission);
return PERMISSION_STATUS_GRANTED;
}
//if no permissions were found then there is an issue and permission is not set in Android manifest
if (names.size() == 0) {
Log.d(LOG_TAG, "No permissions found in manifest for: $permission");
Log.d(LOG_TAG, "No permissions found in manifest for: " + permission);
return PERMISSION_STATUS_UNKNOWN;
}
......@@ -249,10 +268,25 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
return PERMISSION_STATUS_UNKNOWN;
}
final boolean targetsMOrHigher = context.getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.M;
final boolean targetsMOrHigher = context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.M;
for (String name : names) {
// Only handle them if the client app actually targets a API level greater than M.
if (targetsMOrHigher) {
if (permission == PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS) {
String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
// PowerManager.isIgnoringBatteryOptimizations has been included in Android M first.
if (VERSION.SDK_INT >= VERSION_CODES.M) {
if (pm.isIgnoringBatteryOptimizations(packageName)) {
return PERMISSION_STATUS_GRANTED;
} else {
return PERMISSION_STATUS_DENIED;
}
} else {
return PERMISSION_STATUS_RESTRICTED;
}
}
final int permissionStatus = ContextCompat.checkSelfPermission(context, name);
if (permissionStatus == PackageManager.PERMISSION_DENIED) {
return PERMISSION_STATUS_DENIED;
......@@ -312,6 +346,10 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
return SERVICE_STATUS_ENABLED;
}
if (permission == PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? SERVICE_STATUS_ENABLED : SERVICE_STATUS_NOT_APPLICABLE;
}
return SERVICE_STATUS_NOT_APPLICABLE;
}
......@@ -326,12 +364,12 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
// if isn't an android specific group then go ahead and return false;
if (names == null) {
Log.d(LOG_TAG, "No android specific permissions needed for: $permission");
Log.d(LOG_TAG, "No android specific permissions needed for: " + permission);
return false;
}
if (names.isEmpty()) {
Log.d(LOG_TAG, "No permissions found in manifest for: $permission no need to show request rationale");
Log.d(LOG_TAG, "No permissions found in manifest for: " + permission + " no need to show request rationale");
return false;
}
......@@ -371,7 +409,15 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
continue;
}
if (permission == PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS) {
String packageName = mRegistrar.context().getPackageName();
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
mRegistrar.activity().startActivityForResult(intent, PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS);
} else {
permissionsToRequest.addAll(names);
}
} else {
if (!mRequestResults.containsKey(permission)) {
mRequestResults.put(permission, PERMISSION_STATUS_GRANTED);
......@@ -429,6 +475,18 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
processResult();
}
private void handleIgnoreBatteryOptimizationsRequest(boolean granted) {
if (mResult == null) {
return;
}
int status = granted ? PERMISSION_STATUS_GRANTED : PERMISSION_STATUS_DENIED;
mRequestResults.put(PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS, status);
processResult();
}
@PermissionStatus
private int toPermissionStatus(int grantResult) {
return grantResult == PackageManager.PERMISSION_GRANTED ? PERMISSION_STATUS_GRANTED : PERMISSION_STATUS_DENIED;
......@@ -533,7 +591,7 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
break;
case PERMISSION_GROUP_SENSORS:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT_WATCH) {
if (hasPermissionInManifest(Manifest.permission.BODY_SENSORS)) {
permissionNames.add(Manifest.permission.BODY_SENSORS);
}
......@@ -565,6 +623,11 @@ public class PermissionHandlerPlugin implements MethodCallHandler {
permissionNames.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
break;
case PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS:
if (VERSION.SDK_INT >= VERSION_CODES.M && hasPermissionInManifest(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))
permissionNames.add(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
break;
case PERMISSION_GROUP_MEDIA_LIBRARY:
case PERMISSION_GROUP_PHOTOS:
case PERMISSION_GROUP_REMINDERS:
......
......@@ -25,6 +25,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SENSORS" />
<uses-permission android:name="android.permission.BODY_SENSORS" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<application
android:name="io.flutter.app.FlutterApplication"
......
......@@ -29,7 +29,9 @@ class MyApp extends StatelessWidget {
if (Platform.isIOS) {
return permission != PermissionGroup.unknown &&
permission != PermissionGroup.sms &&
permission != PermissionGroup.storage;
permission != PermissionGroup.storage &&
permission !=
PermissionGroup.ignoreBatteryOptimizations;
} else {
return permission != PermissionGroup.unknown &&
permission != PermissionGroup.mediaLibrary &&
......
......@@ -21,6 +21,7 @@ typedef NS_ENUM(int, PermissionGroup) {
PermissionGroupSms,
PermissionGroupSpeech,
PermissionGroupStorage,
PermissionGroupIgnoreBatteryOptimizations,
PermissionGroupUnknown,
};
......
......@@ -3,7 +3,7 @@
#
Pod::Spec.new do |s|
s.name = 'permission_handler'
s.version = '3.1.0'
s.version = '3.2.0'
s.summary = 'Permission plugin for Flutter.'
s.description = <<-DESC
A new Flutter project.
......
......@@ -143,8 +143,12 @@ class PermissionGroup {
/// iOS: Nothing
static const PermissionGroup storage = PermissionGroup._(14);
/// Android: Ignore Battery Optimizations
static const PermissionGroup ignoreBatteryOptimizations =
PermissionGroup._(15);
/// The unknown permission only used for return type, never requested
static const PermissionGroup unknown = PermissionGroup._(15);
static const PermissionGroup unknown = PermissionGroup._(16);
static const List<PermissionGroup> values = <PermissionGroup>[
calendar,
......@@ -162,6 +166,7 @@ class PermissionGroup {
sms,
speech,
storage,
ignoreBatteryOptimizations,
unknown,
];
......@@ -181,6 +186,7 @@ class PermissionGroup {
'sms',
'speech',
'storage',
'ignoreBatteryOptimizations',
'unknown',
];
......
name: permission_handler
description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
version: 3.1.0
version: 3.2.0
authors:
- Baseflow <hello@baseflow.com>
- long1eu <home@long1.eu>
......
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