Commit 138f5a55 by Maurits van Beusekom Committed by GitHub

Merge pull request #72 from BaseflowIT/releases/2.1.3

Prepare for release 2.1.3
parents 42fdd90c 89b8b5cf
## 2.1.3
* Fixed bug on iOS where result of the `openAppSettings` call always returned `false`;
* Upgrade Android plugin to support AndroidX and latest Gradle and Kotlin versions;
* Added Swift version number to the Podfile of the plugin;
* Updated flutter static analyzes to conform to latest recommendations.
## 2.1.2
* Make sure the Permission Handler compiles with latest iOS SDK
......@@ -28,4 +35,4 @@
## 1.0.0
* Initial release.
\ No newline at end of file
* Initial release.
......@@ -22,7 +22,7 @@ To use this plugin, add `permission_handler` as a [dependency in your pubspec.ya
```yaml
dependencies:
permission_handler: '^2.1.2'
permission_handler: '^2.1.3'
```
> **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.
......@@ -143,7 +143,7 @@ enum PermissionStatus {
/// Permission to access the requested feature is denied by the user.
denied,
/// The feature is disabled (or not available) on the device.
/// Permissions to access the feature is granted by the user but the feature is disabled.
disabled,
/// Permission to access the requested feature is granted by the user.
......
......@@ -28,6 +28,10 @@ analyzer:
missing_return: warning
# allow having TODOs in the code
todo: ignore
# Ignore analyzer hints for updating pubspecs when using Future or
# Stream and not importing dart:async
# Please see https://github.com/flutter/flutter/pull/24528 for details.
#sdk_version_async_exported_from_core: ignore
exclude:
- 'bin/cache/**'
# the following two are relative to the stocks example and the flutter package respectively
......@@ -56,6 +60,7 @@ linter:
- avoid_empty_else
- avoid_field_initializers_in_const_classes
- avoid_function_literals_in_foreach_calls
# - avoid_implementing_value_types # not yet tested
- avoid_init_to_null
# - avoid_js_rounded_ints # only useful when targeting JS runtime
- avoid_null_checks_in_equality_operators
......@@ -65,8 +70,11 @@ linter:
- avoid_renaming_method_parameters
- avoid_return_types_on_setters
# - avoid_returning_null # there are plenty of valid reasons to return null
# - avoid_returning_null_for_future # not yet tested
- avoid_returning_null_for_void
# - avoid_returning_this # there are plenty of valid reasons to return this
# - avoid_setters_without_getters # not yet tested
# - avoid_shadowing_type_parameters # not yet tested
# - avoid_single_cascade_in_expression_statements # not yet tested
- avoid_slow_async_io
- avoid_types_as_parameter_names
......@@ -87,6 +95,7 @@ linter:
- empty_constructor_bodies
- empty_statements
# - file_names # not yet tested
- flutter_style_todos
- hash_and_equals
- implementation_imports
# - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811
......@@ -111,7 +120,6 @@ linter:
# - parameter_assignments # we do this commonly
- prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists
- prefer_bool_in_asserts
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
......@@ -128,6 +136,7 @@ linter:
# - prefer_function_declarations_over_variables # not yet tested
- prefer_generic_function_type_aliases
- prefer_initializing_formals
# - prefer_int_literals # not yet tested
# - prefer_interpolation_to_compose_strings # not yet tested
- prefer_is_empty
- prefer_is_not_empty
......@@ -140,6 +149,7 @@ linter:
- recursive_getters
- slash_for_doc_comments
- sort_constructors_first
- sort_pub_dependencies
- sort_unnamed_constructors_first
- super_goes_last
- test_types_in_equals
......@@ -147,6 +157,7 @@ linter:
# - type_annotate_public_apis # subset of always_specify_types
- type_init_formals
# - unawaited_futures # too many false positives
# - unnecessary_await_in_return # not yet tested
- unnecessary_brace_in_string_interps
- unnecessary_const
- unnecessary_getters_setters
......@@ -159,6 +170,7 @@ linter:
- unnecessary_statements
- unnecessary_this
- unrelated_type_equality_checks
# - use_function_type_syntax_for_parameters # not yet tested
- use_rethrow_when_possible
# - use_setters_to_change_properties # not yet tested
# - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
......
connection.project.dir=
connection.project.dir=../example/android
eclipse.preferences.version=1
......@@ -2,7 +2,7 @@ group 'com.baseflow.permissionhandler'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.2.71'
ext.kotlin_version = '1.3.0'
repositories {
google()
jcenter()
......@@ -25,14 +25,14 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 27
compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 16
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
......@@ -40,7 +40,7 @@ android {
}
dependencies {
api "com.android.support:support-compat:27.1.1"
api 'androidx.core:core:1.0.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "com.google.code.gson:gson:2.8.5"
......
......@@ -7,8 +7,8 @@ import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Build
import android.provider.Settings
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import android.util.Log
import com.baseflow.permissionhandler.data.PermissionGroup
import com.baseflow.permissionhandler.data.PermissionStatus
......@@ -149,8 +149,13 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ
val targetsMOrHigher = context.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.M
for (name in names) {
if (targetsMOrHigher && ContextCompat.checkSelfPermission(context, name) != PackageManager.PERMISSION_GRANTED) {
return PermissionStatus.DENIED
if (targetsMOrHigher) {
val permissionStatus = ContextCompat.checkSelfPermission(context, name)
if (permissionStatus == PackageManager.PERMISSION_DENIED) {
return PermissionStatus.DENIED
} else if (permissionStatus != PackageManager.PERMISSION_GRANTED) {
return PermissionStatus.UNKNOWN
}
}
}
......@@ -258,7 +263,10 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ
} else if (permission == PermissionGroup.LOCATION) {
val context: Context? = registrar.activity() ?: registrar.activeContext()
val isLocationServiceEnabled= if (context == null) false else isLocationServiceEnabled(context)
val permissionStatus = if (isLocationServiceEnabled) grantResults[i].toPermissionStatus() else PermissionStatus.DISABLED
var permissionStatus = grantResults[i].toPermissionStatus()
if (permissionStatus == PermissionStatus.GRANTED && !isLocationServiceEnabled) {
permissionStatus = PermissionStatus.DISABLED
}
if (!mRequestResults.containsKey(PermissionGroup.LOCATION_ALWAYS)) {
mRequestResults[PermissionGroup.LOCATION_ALWAYS] = permissionStatus
......
......@@ -16,7 +16,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 27
compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
......@@ -30,10 +30,10 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.baseflow.permissionhandlerexample"
minSdkVersion 16
targetSdkVersion 27
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
......@@ -52,6 +52,6 @@ flutter {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
}
buildscript {
ext.kotlin_version = '1.2.71'
ext.kotlin_version = '1.3.0'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'com.android.tools.build:gradle:3.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
......
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M
......@@ -8,7 +8,6 @@
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
......@@ -39,7 +38,6 @@
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
36F84C9A972D968241208A7F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
......@@ -81,7 +79,6 @@
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
......@@ -207,7 +204,6 @@
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -222,7 +218,7 @@
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/permission_handler/permission_handler.framework",
);
name = "[CP] Embed Pods Frameworks";
......
......@@ -16,7 +16,8 @@ class MyApp extends StatelessWidget {
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
PermissionHandler().openAppSettings();
PermissionHandler().openAppSettings().then((bool hasOpened) =>
debugPrint('App Settings opened: ' + hasOpened.toString()));
},
)
],
......
......@@ -49,12 +49,14 @@ class PermissionManager: NSObject {
if #available(iOS 10, *) {
guard let url = URL(string: UIApplication.openSettingsURLString),
UIApplication.shared.canOpenURL(url) else {
result(false)
return
}
let optionsKeyDictionary = [UIApplication.OpenExternalURLOptionsKey(rawValue: "universalLinksOnly"): NSNumber(value: true)]
UIApplication.shared.open(url, options: optionsKeyDictionary, completionHandler: nil)
UIApplication.shared.open(url, options: optionsKeyDictionary, completionHandler: { (success) in result(success) });
return
} else {
let success = UIApplication.shared.openURL(URL.init(string: UIApplication.openSettingsURLString)!)
result(success)
......
......@@ -18,15 +18,16 @@ class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManag
}
private static func getPermissionStatus(permission: PermissionGroup) -> PermissionStatus {
if !CLLocationManager.locationServicesEnabled() {
let authorizationStatus: CLAuthorizationStatus = CLLocationManager.authorizationStatus()
let permissionStatus: PermissionStatus = LocationPermissionStrategy.determinePermissionStatus(
permission: permission,
authorizationStatus: authorizationStatus)
if permissionStatus == PermissionStatus.granted && !CLLocationManager.locationServicesEnabled() {
return PermissionStatus.disabled
}
let status: CLAuthorizationStatus = CLLocationManager.authorizationStatus()
return LocationPermissionStrategy.determinePermissionStatus(
permission: permission,
authorizationStatus: status)
return permissionStatus
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) {
......
......@@ -15,22 +15,25 @@ class SensorPermissionStrategy : NSObject, PermissionStrategy {
}
private static func getPermissionStatus() -> PermissionStatus {
if !CMMotionActivityManager.isActivityAvailable() {
return PermissionStatus.disabled
}
if #available(iOS 11.0, *) {
let status: CMAuthorizationStatus = CMMotionActivityManager.authorizationStatus()
var permissionStatus: PermissionStatus
switch status {
case CMAuthorizationStatus.authorized:
return PermissionStatus.granted
permissionStatus = PermissionStatus.granted
case CMAuthorizationStatus.denied:
return PermissionStatus.denied
permissionStatus = PermissionStatus.denied
case CMAuthorizationStatus.restricted:
return PermissionStatus.restricted
permissionStatus = PermissionStatus.restricted
default:
return PermissionStatus.unknown
permissionStatus = PermissionStatus.unknown
}
if permissionStatus == PermissionStatus.granted && !CMMotionActivityManager.isActivityAvailable() {
return PermissionStatus.disabled
} else {
return permissionStatus
}
}
......
......@@ -3,7 +3,7 @@
#
Pod::Spec.new do |s|
s.name = 'permission_handler'
s.version = '2.1.2'
s.version = '2.1.3'
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.
......@@ -15,7 +15,7 @@ Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Andro
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.swift_version = '4.2'
s.ios.deployment_target = '8.0'
s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.2' }
end
......
......@@ -32,7 +32,7 @@ class PermissionHandler {
/// Returns a [Future] containing the current permission status for the supplied [PermissionGroup].
Future<PermissionStatus> checkPermissionStatus(
PermissionGroup permission) async {
final dynamic status = await _methodChannel.invokeMethod(
final String status = await _methodChannel.invokeMethod(
'checkPermissionStatus', Codec.encodePermissionGroup(permission));
return Codec.decodePermissionStatus(status);
......@@ -52,7 +52,7 @@ class PermissionHandler {
Future<Map<PermissionGroup, PermissionStatus>> requestPermissions(
List<PermissionGroup> permissions) async {
final String jsonData = Codec.encodePermissionGroups(permissions);
final dynamic status =
final String status =
await _methodChannel.invokeMethod('requestPermissions', jsonData);
return Codec.decodePermissionRequestResult(status);
......
part of permission_handler;
class Codec {
static PermissionStatus decodePermissionStatus(dynamic value) {
final dynamic permission = json.decode(value.toString());
static PermissionStatus decodePermissionStatus(String value) {
final dynamic permission = json.decode(value);
return PermissionStatus.values.firstWhere(
(PermissionStatus e) => e.toString().split('.').last == permission);
}
static Map<PermissionGroup, PermissionStatus> decodePermissionRequestResult(
dynamic value) {
final Map<String, dynamic> jsonObject = json.decode(value.toString());
String value) {
final Map<String, dynamic> jsonObject = json.decode(value);
final Map<PermissionGroup, PermissionStatus> permissionResults =
<PermissionGroup, PermissionStatus>{};
......
name: permission_handler
description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
version: 2.1.2
version: 2.1.3
author: Baseflow <hello@baseflow.com>
homepage: https://github.com/baseflowit/flutter-permission-handler
......@@ -20,7 +20,7 @@ flutter:
pluginClass: PermissionHandlerPlugin
environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0"
sdk: ">=2.1.0-dev.5.0 <3.0.0"
# To add assets to your plugin package, add an assets section, like this:
# assets:
......
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