Commit b8509db6 by Maurits van Beusekom Committed by GitHub

Merge pull request #75 from BaseflowIT/features/check_service_status

 Added option to check service status
parents 33b0bad1 b3d010c7
...@@ -14,7 +14,7 @@ matrix: ...@@ -14,7 +14,7 @@ matrix:
- libstdc++6 - libstdc++6
- fonts-droid - fonts-droid
before_script: before_script:
- git clone https://github.com/flutter/flutter.git $HOME/flutter - git clone --single-branch --branch stable https://github.com/flutter/flutter.git $HOME/flutter
- export PATH=$HOME/flutter/bin:$HOME/flutter/bin/cache/dart-sdk/bin:$PATH - export PATH=$HOME/flutter/bin:$HOME/flutter/bin/cache/dart-sdk/bin:$PATH
- flutter doctor - flutter doctor
script: script:
......
## 2.2.0
* Added new method `checkServiceStatus` to allow users to check if the location services (on Android and iOS) and motion services (iOS only) are enabled;
* When checking permission status (using `checkPermissionStatus`) return `PermissionStatus.disabled` when permissions are granted or denied and the location services (on Android and iOS) or the motion services (iOS only) are disabled.
## 2.1.3 ## 2.1.3
* Fixed bug on iOS where result of the `openAppSettings` call always returned `false`; * Fixed bug on iOS where result of the `openAppSettings` call always returned `false`;
......
...@@ -22,7 +22,7 @@ To use this plugin, add `permission_handler` as a [dependency in your pubspec.ya ...@@ -22,7 +22,7 @@ To use this plugin, add `permission_handler` as a [dependency in your pubspec.ya
```yaml ```yaml
dependencies: dependencies:
permission_handler: '^2.1.3' permission_handler: '^2.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:** 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.
...@@ -31,7 +31,7 @@ dependencies: ...@@ -31,7 +31,7 @@ dependencies:
### Requesting permission ### Requesting permission
``` dart ```dart
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().requestPermissions([PermissionGroup.contacts]); Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().requestPermissions([PermissionGroup.contacts]);
...@@ -39,15 +39,25 @@ Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().r ...@@ -39,15 +39,25 @@ Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().r
### Checking permission ### Checking permission
``` dart ```dart
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
PermissionStatus permission = await PermissionHandler().checkPermissionStatus(PermissionGroup.contacts); PermissionStatus permission = await PermissionHandler().checkPermissionStatus(PermissionGroup.contacts);
``` ```
### Checking service status
```dart
import 'package:permission_handler/permission_handler.dart';
ServiceStatus serviceStatus = await PermissionHandler().checkServiceStatus(PermissionGroup.location);
```
Checking the service status only makes sense for the `PermissionGroup.location` on Android and the `PermissionGroup.location`, `PermissionGroup.locationWhenInUser`, `PermissionGroup.locationAlways` or `PermissionGroup.sensors` on iOS. All other permission groups are not backed by a separate service and will always return `ServiceStatus.notApplicable`.
### Open app settings ### Open app settings
``` dart ```dart
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
bool isOpened = await PermissionHandler().openAppSettings(); bool isOpened = await PermissionHandler().openAppSettings();
...@@ -55,7 +65,7 @@ bool isOpened = await PermissionHandler().openAppSettings(); ...@@ -55,7 +65,7 @@ bool isOpened = await PermissionHandler().openAppSettings();
### Show a rationale for requesting permission (Android only) ### Show a rationale for requesting permission (Android only)
``` dart ```dart
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
bool isShown = await PermissionHandler().shouldShowRequestPermissionRationale(PermissionGroup.contacts); bool isShown = await PermissionHandler().shouldShowRequestPermissionRationale(PermissionGroup.contacts);
...@@ -67,7 +77,7 @@ This will always return `false` on iOS. ...@@ -67,7 +77,7 @@ This will always return `false` on iOS.
Defines the permission groups for which permissions can be checked or requested. Defines the permission groups for which permissions can be checked or requested.
``` dart ```dart
enum PermissionGroup { enum PermissionGroup {
/// The unknown permission only used for return type, never requested /// The unknown permission only used for return type, never requested
unknown, unknown,
...@@ -138,7 +148,7 @@ enum PermissionGroup { ...@@ -138,7 +148,7 @@ enum PermissionGroup {
Defines the state of a permission group Defines the state of a permission group
``` dart ```dart
enum PermissionStatus { enum PermissionStatus {
/// Permission to access the requested feature is denied by the user. /// Permission to access the requested feature is denied by the user.
denied, denied,
...@@ -157,6 +167,27 @@ enum PermissionStatus { ...@@ -157,6 +167,27 @@ enum PermissionStatus {
} }
``` ```
### Overview of possible service statuses
Defines the state of the backing service for the supplied permission group
```dart
/// Defines the state of a service related to the permission group
enum ServiceStatus {
/// The unknown service status indicates the state of the service could not be determined.
unknown,
/// There is no service for the supplied permission group.
notApplicable,
/// The service for the supplied permission group is disabled.
disabled,
/// The service for the supplied permission group is enabled.
enabled
}
```
## Issues ## Issues
Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/BaseflowIT/flutter-permission-handler/issues) page. Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/BaseflowIT/flutter-permission-handler/issues) page.
......
...@@ -12,6 +12,7 @@ import androidx.core.content.ContextCompat ...@@ -12,6 +12,7 @@ import androidx.core.content.ContextCompat
import android.util.Log import android.util.Log
import com.baseflow.permissionhandler.data.PermissionGroup import com.baseflow.permissionhandler.data.PermissionGroup
import com.baseflow.permissionhandler.data.PermissionStatus import com.baseflow.permissionhandler.data.PermissionStatus
import com.baseflow.permissionhandler.data.ServiceStatus
import com.baseflow.permissionhandler.utils.Codec import com.baseflow.permissionhandler.utils.Codec
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.MethodCallHandler
...@@ -99,7 +100,14 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ ...@@ -99,7 +100,14 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ
call.method == "checkPermissionStatus" -> { call.method == "checkPermissionStatus" -> {
val permission = Codec.decodePermissionGroup(call.arguments) val permission = Codec.decodePermissionGroup(call.arguments)
val permissionStatus = checkPermissionStatus(permission) val permissionStatus = checkPermissionStatus(permission)
handleSuccess(permissionStatus, result)
result?.success(Codec.encodePermissionStatus(permissionStatus))
}
call.method == "checkServiceStatus" -> {
val permission = Codec.decodePermissionGroup(call.arguments)
val serviceStatus = checkServiceStatus(permission)
result?.success(Codec.encodeServiceStatus(serviceStatus))
} }
call.method == "requestPermissions" -> { call.method == "requestPermissions" -> {
if (mResult != null) { if (mResult != null) {
...@@ -168,6 +176,20 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ ...@@ -168,6 +176,20 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ
return PermissionStatus.GRANTED return PermissionStatus.GRANTED
} }
private fun checkServiceStatus(permission: PermissionGroup) : ServiceStatus {
val context: Context? = registrar.activity() ?: registrar.activeContext()
if (context == null) {
Log.d(mLogTag, "Unable to detect current Activity or App Context.")
return ServiceStatus.UNKNOWN
}
if (permission == PermissionGroup.LOCATION || permission == PermissionGroup.LOCATION_ALWAYS || permission == PermissionGroup.LOCATION_WHEN_IN_USE) {
return if(isLocationServiceEnabled(context)) ServiceStatus.ENABLED else ServiceStatus.DISABLED
}
return ServiceStatus.NOT_APPLICABLE
}
private fun shouldShowRequestPermissionRationale(permission: PermissionGroup) : Boolean { private fun shouldShowRequestPermissionRationale(permission: PermissionGroup) : Boolean {
val activity = registrar.activity() val activity = registrar.activity()
if(activity == null) if(activity == null)
...@@ -479,8 +501,4 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ ...@@ -479,8 +501,4 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ
return !TextUtils.isEmpty(locationProviders) return !TextUtils.isEmpty(locationProviders)
} }
} }
private fun handleSuccess(permissionStatus: PermissionStatus, result: Result?) {
result?.success(Codec.encodePermissionStatus(permissionStatus))
}
} }
package com.baseflow.permissionhandler.data
import com.google.gson.annotations.SerializedName
enum class ServiceStatus {
@SerializedName("unknown")
UNKNOWN,
@SerializedName("disabled")
DISABLED,
@SerializedName("enabled")
ENABLED,
@SerializedName("notApplicable")
NOT_APPLICABLE,
}
\ No newline at end of file
...@@ -2,6 +2,7 @@ package com.baseflow.permissionhandler.utils ...@@ -2,6 +2,7 @@ package com.baseflow.permissionhandler.utils
import com.baseflow.permissionhandler.data.PermissionGroup import com.baseflow.permissionhandler.data.PermissionGroup
import com.baseflow.permissionhandler.data.PermissionStatus import com.baseflow.permissionhandler.data.PermissionStatus
import com.baseflow.permissionhandler.data.ServiceStatus
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
...@@ -29,6 +30,11 @@ class Codec { ...@@ -29,6 +30,11 @@ class Codec {
} }
@JvmStatic @JvmStatic
fun encodeServiceStatus(serviceStatus: ServiceStatus) : String {
return gsonDecoder.toJson(serviceStatus)
}
@JvmStatic
fun encodePermissionRequestResult(permissionResults: Map<PermissionGroup, PermissionStatus>) : String { fun encodePermissionRequestResult(permissionResults: Map<PermissionGroup, PermissionStatus>) : String {
val jsonString = gsonDecoder.toJson(permissionResults) val jsonString = gsonDecoder.toJson(permissionResults)
return jsonString return jsonString
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 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 */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 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, ); }; }; 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
...@@ -38,6 +39,7 @@ ...@@ -38,6 +39,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 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>"; }; 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; }; 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>"; }; 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>"; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
...@@ -81,6 +83,7 @@ ...@@ -81,6 +83,7 @@
children = ( children = (
3B80C3931E831B6300D905FE /* App.framework */, 3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */, 9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
...@@ -203,6 +206,7 @@ ...@@ -203,6 +206,7 @@
files = ( files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
); );
...@@ -218,7 +222,7 @@ ...@@ -218,7 +222,7 @@
); );
inputPaths = ( inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", "${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/permission_handler/permission_handler.framework", "${BUILT_PRODUCTS_DIR}/permission_handler/permission_handler.framework",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
......
...@@ -98,12 +98,28 @@ class _PermissionState extends State<PermissionWidget> { ...@@ -98,12 +98,28 @@ class _PermissionState extends State<PermissionWidget> {
_permissionStatus.toString(), _permissionStatus.toString(),
style: TextStyle(color: getPermissionColor()), style: TextStyle(color: getPermissionColor()),
), ),
onTap: () async { trailing: IconButton(
icon: const Icon(Icons.info),
onPressed: () {
checkServiceStatus(context, _permissionGroup);
}),
onTap: () {
requestPermission(_permissionGroup); requestPermission(_permissionGroup);
}, },
); );
} }
void checkServiceStatus(BuildContext context, PermissionGroup permission) {
PermissionHandler()
.checkServiceStatus(permission)
.then((ServiceStatus serviceStatus) {
final SnackBar snackBar =
SnackBar(content: Text(serviceStatus.toString()));
Scaffold.of(context).showSnackBar(snackBar);
});
}
void requestPermission(PermissionGroup permission) { void requestPermission(PermissionGroup permission) {
final List<PermissionGroup> permissions = <PermissionGroup>[permission]; final List<PermissionGroup> permissions = <PermissionGroup>[permission];
final Future<Map<PermissionGroup, PermissionStatus>> requestFuture = final Future<Map<PermissionGroup, PermissionStatus>> requestFuture =
......
...@@ -22,6 +22,13 @@ class PermissionManager: NSObject { ...@@ -22,6 +22,13 @@ class PermissionManager: NSObject {
result(Codec.encodePermissionStatus(permissionStatus: permissionStatus)) result(Codec.encodePermissionStatus(permissionStatus: permissionStatus))
} }
static func checkServiceStatus(permission: PermissionGroup, result: @escaping FlutterResult) {
let permissionStrategy = PermissionManager.createPermissionStrategy(permission: permission)
let serviceStatus = permissionStrategy.checkServiceStatus(permission: permission)
result(Codec.encodeServiceStatus(serviceStatus: serviceStatus))
}
func requestPermissions(permissions: [PermissionGroup], completion: @escaping PermissionRequestCompletion) { func requestPermissions(permissions: [PermissionGroup], completion: @escaping PermissionRequestCompletion) {
var requestQueue = Set(permissions.map { $0 }) var requestQueue = Set(permissions.map { $0 })
var permissionStatusResult: [PermissionGroup: PermissionStatus] = [:] var permissionStatusResult: [PermissionGroup: PermissionStatus] = [:]
......
...@@ -25,6 +25,12 @@ public class SwiftPermissionHandlerPlugin: NSObject, FlutterPlugin { ...@@ -25,6 +25,12 @@ public class SwiftPermissionHandlerPlugin: NSObject, FlutterPlugin {
PermissionManager.checkPermissionStatus( PermissionManager.checkPermissionStatus(
permission: permission, permission: permission,
result: result) result: result)
} else if call.method == "checkServiceStatus" {
let permission: PermissionGroup = Codec.decodePermissionGroup(from: call.arguments)
PermissionManager.checkServiceStatus(
permission: permission,
result: result)
} else if call.method == "requestPermissions" { } else if call.method == "requestPermissions" {
if _methodResult != nil { if _methodResult != nil {
result(FlutterError( result(FlutterError(
......
//
// ServiceStatus.swift
// permission_handler
//
// Created by Maurits van Beusekom on 12/02/2019.
//
import Foundation
enum ServiceStatus : String, Codable {
case disabled = "disabled"
case enabled = "enabled"
case notApplicable = "notApplicable"
case unknown = "unknown"
}
...@@ -19,6 +19,10 @@ class AudioVideoPermissionStrategy : NSObject, PermissionStrategy { ...@@ -19,6 +19,10 @@ class AudioVideoPermissionStrategy : NSObject, PermissionStrategy {
return PermissionStatus.unknown return PermissionStatus.unknown
} }
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus {
return ServiceStatus.notApplicable
}
private static func getPermissionStatus(mediaType: AVMediaType) -> PermissionStatus { private static func getPermissionStatus(mediaType: AVMediaType) -> PermissionStatus {
let status: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: mediaType) let status: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: mediaType)
......
...@@ -45,6 +45,10 @@ class ContactPermissionStrategy : NSObject, PermissionStrategy { ...@@ -45,6 +45,10 @@ class ContactPermissionStrategy : NSObject, PermissionStrategy {
} }
} }
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus {
return ServiceStatus.notApplicable
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) { func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) {
let permissionStatus = checkPermissionStatus(permission: permission) let permissionStatus = checkPermissionStatus(permission: permission)
......
...@@ -36,6 +36,10 @@ class EventPermissionStrategy : NSObject, PermissionStrategy { ...@@ -36,6 +36,10 @@ class EventPermissionStrategy : NSObject, PermissionStrategy {
} }
} }
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus {
return ServiceStatus.notApplicable
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) { func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) {
let permissionStatus = checkPermissionStatus(permission: permission) let permissionStatus = checkPermissionStatus(permission: permission)
......
...@@ -23,13 +23,19 @@ class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManag ...@@ -23,13 +23,19 @@ class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManag
permission: permission, permission: permission,
authorizationStatus: authorizationStatus) authorizationStatus: authorizationStatus)
if permissionStatus == PermissionStatus.granted && !CLLocationManager.locationServicesEnabled() { if (permissionStatus == PermissionStatus.granted || permissionStatus == PermissionStatus.denied) && !CLLocationManager.locationServicesEnabled() {
return PermissionStatus.disabled return PermissionStatus.disabled
} }
return permissionStatus return permissionStatus
} }
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus {
return CLLocationManager.locationServicesEnabled()
? ServiceStatus.enabled
: ServiceStatus.disabled
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) { func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) {
let permissionStatus = checkPermissionStatus(permission: permission) let permissionStatus = checkPermissionStatus(permission: permission)
......
...@@ -24,6 +24,10 @@ class MediaLibraryPermissionStrategy : NSObject, PermissionStrategy { ...@@ -24,6 +24,10 @@ class MediaLibraryPermissionStrategy : NSObject, PermissionStrategy {
return PermissionStatus.unknown return PermissionStatus.unknown
} }
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus {
return ServiceStatus.notApplicable
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) -> Void { func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) -> Void {
let status = checkPermissionStatus(permission: permission) let status = checkPermissionStatus(permission: permission)
if status != PermissionStatus.unknown { if status != PermissionStatus.unknown {
......
...@@ -11,5 +11,6 @@ typealias PermissionStatusHandler = (_ permissionStatus: PermissionStatus) -> Vo ...@@ -11,5 +11,6 @@ typealias PermissionStatusHandler = (_ permissionStatus: PermissionStatus) -> Vo
protocol PermissionStrategy { protocol PermissionStrategy {
func checkPermissionStatus(permission: PermissionGroup) -> PermissionStatus func checkPermissionStatus(permission: PermissionGroup) -> PermissionStatus
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler)
} }
...@@ -20,6 +20,10 @@ class PhotoPermissionStrategy : NSObject, PermissionStrategy { ...@@ -20,6 +20,10 @@ class PhotoPermissionStrategy : NSObject, PermissionStrategy {
return PhotoPermissionStrategy.determinePermissionStatus(authorizationStatus: status) return PhotoPermissionStrategy.determinePermissionStatus(authorizationStatus: status)
} }
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus {
return ServiceStatus.notApplicable
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) { func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) {
let status = checkPermissionStatus(permission: permission) let status = checkPermissionStatus(permission: permission)
......
...@@ -30,7 +30,7 @@ class SensorPermissionStrategy : NSObject, PermissionStrategy { ...@@ -30,7 +30,7 @@ class SensorPermissionStrategy : NSObject, PermissionStrategy {
permissionStatus = PermissionStatus.unknown permissionStatus = PermissionStatus.unknown
} }
if permissionStatus == PermissionStatus.granted && !CMMotionActivityManager.isActivityAvailable() { if (permissionStatus == PermissionStatus.granted || permissionStatus == PermissionStatus.denied) && !CMMotionActivityManager.isActivityAvailable() {
return PermissionStatus.disabled return PermissionStatus.disabled
} else { } else {
return permissionStatus return permissionStatus
...@@ -40,6 +40,16 @@ class SensorPermissionStrategy : NSObject, PermissionStrategy { ...@@ -40,6 +40,16 @@ class SensorPermissionStrategy : NSObject, PermissionStrategy {
return PermissionStatus.unknown return PermissionStatus.unknown
} }
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus {
if #available(iOS 11.0, *) {
return CMMotionActivityManager.isActivityAvailable()
? ServiceStatus.enabled
: ServiceStatus.disabled
}
return ServiceStatus.unknown
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) { func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) {
let status = checkPermissionStatus(permission: permission) let status = checkPermissionStatus(permission: permission)
......
...@@ -24,6 +24,10 @@ class SpeechPermissionStrategy : NSObject, PermissionStrategy { ...@@ -24,6 +24,10 @@ class SpeechPermissionStrategy : NSObject, PermissionStrategy {
return PermissionStatus.unknown return PermissionStatus.unknown
} }
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus {
return ServiceStatus.notApplicable
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) { func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) {
let status = checkPermissionStatus(permission: permission) let status = checkPermissionStatus(permission: permission)
......
...@@ -12,6 +12,10 @@ class UnknownPermissionStrategy : NSObject, PermissionStrategy { ...@@ -12,6 +12,10 @@ class UnknownPermissionStrategy : NSObject, PermissionStrategy {
return PermissionStatus.unknown return PermissionStatus.unknown
} }
func checkServiceStatus(permission: PermissionGroup) -> ServiceStatus {
return ServiceStatus.unknown
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) { func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) {
completionHandler(PermissionStatus.unknown) completionHandler(PermissionStatus.unknown)
} }
......
...@@ -31,6 +31,11 @@ struct Codec { ...@@ -31,6 +31,11 @@ struct Codec {
return status return status
} }
static func encodeServiceStatus(serviceStatus: ServiceStatus) -> String? {
let status = "\"" + serviceStatus.rawValue + "\""
return status
}
static func encodePermissionRequestResult(permissionStatusResult: [PermissionGroup: PermissionStatus]) -> String? { static func encodePermissionRequestResult(permissionStatusResult: [PermissionGroup: PermissionStatus]) -> String? {
let jsonDict = Dictionary(uniqueKeysWithValues: let jsonDict = Dictionary(uniqueKeysWithValues:
permissionStatusResult.map { permissionStatusResult.map {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'permission_handler' s.name = 'permission_handler'
s.version = '2.1.3' s.version = '2.2.0'
s.summary = 'Permission plugin for Flutter.' s.summary = 'Permission plugin for Flutter.'
s.description = <<-DESC s.description = <<-DESC
Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
......
...@@ -18,6 +18,21 @@ enum PermissionStatus { ...@@ -18,6 +18,21 @@ enum PermissionStatus {
unknown unknown
} }
/// Defines the state of a service related to the permission group
enum ServiceStatus {
/// The unknown service status indicates the state of the service could not be determined.
unknown,
/// There is no service for the supplied permission group.
notApplicable,
/// The service for the supplied permission group is disabled.
disabled,
/// The service for the supplied permission group is enabled.
enabled
}
/// Defines the permission groups for which permissions can be checked or requested. /// Defines the permission groups for which permissions can be checked or requested.
enum PermissionGroup { enum PermissionGroup {
/// The unknown permission only used for return type, never requested /// The unknown permission only used for return type, never requested
......
...@@ -29,6 +29,8 @@ class PermissionHandler { ...@@ -29,6 +29,8 @@ class PermissionHandler {
final MethodChannel _methodChannel; final MethodChannel _methodChannel;
/// Check current permission status.
///
/// Returns a [Future] containing the current permission status for the supplied [PermissionGroup]. /// Returns a [Future] containing the current permission status for the supplied [PermissionGroup].
Future<PermissionStatus> checkPermissionStatus( Future<PermissionStatus> checkPermissionStatus(
PermissionGroup permission) async { PermissionGroup permission) async {
...@@ -38,11 +40,22 @@ class PermissionHandler { ...@@ -38,11 +40,22 @@ class PermissionHandler {
return Codec.decodePermissionStatus(status); return Codec.decodePermissionStatus(status);
} }
/// Check current service status.
///
/// Returns a [Future] containing the current service status for the supplied [PermissionGroup].
Future<ServiceStatus> checkServiceStatus(PermissionGroup permission) async {
final String status = await _methodChannel.invokeMethod(
'checkServiceStatus', Codec.encodePermissionGroup(permission));
return Codec.decodeServiceStatus(status);
}
/// Open the App settings page. /// Open the App settings page.
/// ///
/// Returns [true] if the app settings page could be opened, otherwise [false] is returned. /// Returns [true] if the app settings page could be opened, otherwise [false] is returned.
Future<bool> openAppSettings() async { Future<bool> openAppSettings() async {
final bool hasOpened = await _methodChannel.invokeMethod('openAppSettings'); final bool hasOpened = await _methodChannel.invokeMethod('openAppSettings');
return hasOpened; return hasOpened;
} }
......
...@@ -2,12 +2,19 @@ part of permission_handler; ...@@ -2,12 +2,19 @@ part of permission_handler;
class Codec { class Codec {
static PermissionStatus decodePermissionStatus(String value) { static PermissionStatus decodePermissionStatus(String value) {
final dynamic permission = json.decode(value); final String permission = json.decode(value);
return PermissionStatus.values.firstWhere( return PermissionStatus.values.firstWhere(
(PermissionStatus e) => e.toString().split('.').last == permission); (PermissionStatus e) => e.toString().split('.').last == permission);
} }
static ServiceStatus decodeServiceStatus(String value) {
final String status = json.decode(value);
return ServiceStatus.values.firstWhere(
(ServiceStatus s) => s.toString().split('.').last == status);
}
static Map<PermissionGroup, PermissionStatus> decodePermissionRequestResult( static Map<PermissionGroup, PermissionStatus> decodePermissionRequestResult(
String value) { String value) {
final Map<String, dynamic> jsonObject = json.decode(value); final Map<String, dynamic> jsonObject = json.decode(value);
......
name: permission_handler name: permission_handler
description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
version: 2.1.3 version: 2.2.0
author: Baseflow <hello@baseflow.com> author: Baseflow <hello@baseflow.com>
homepage: https://github.com/baseflowit/flutter-permission-handler homepage: https://github.com/baseflowit/flutter-permission-handler
......
...@@ -20,7 +20,7 @@ unzip -qq gradle-4.1-bin.zip -d $HOME/gradle-4.1 ...@@ -20,7 +20,7 @@ unzip -qq gradle-4.1-bin.zip -d $HOME/gradle-4.1
export GRADLE_HOME=$HOME/gradle-4.1 export GRADLE_HOME=$HOME/gradle-4.1
export PATH=$GRADLE_HOME/bin:$PATH export PATH=$GRADLE_HOME/bin:$PATH
gradle -v gradle -v
git clone https://github.com/flutter/flutter.git $HOME/flutter git clone --single-branch --branch stable https://github.com/flutter/flutter.git $HOME/flutter
export PATH=$HOME/flutter/bin:$HOME/flutter/bin/cache/dart-sdk/bin:$PATH export PATH=$HOME/flutter/bin:$HOME/flutter/bin/cache/dart-sdk/bin:$PATH
flutter doctor flutter doctor
...@@ -5,6 +5,6 @@ brew install ideviceinstaller ...@@ -5,6 +5,6 @@ brew install ideviceinstaller
brew install ios-deploy brew install ios-deploy
pod repo update pod repo update
gem update cocoapods gem update cocoapods
git clone https://github.com/flutter/flutter.git $HOME/flutter git clone --single-branch --branch stable https://github.com/flutter/flutter.git $HOME/flutter
export PATH=$HOME/flutter/bin:$HOME/flutter/bin/cache/dart-sdk/bin:$PATH export PATH=$HOME/flutter/bin:$HOME/flutter/bin/cache/dart-sdk/bin:$PATH
flutter doctor flutter doctor
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