Commit c95a87f8 by Maurits van Beusekom

Implement example app and fix some bugs

parent 8f659480
...@@ -220,10 +220,14 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ ...@@ -220,10 +220,14 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ
} }
} }
ActivityCompat.requestPermissions( if (permissionsToRequest.count() > 0) {
registrar.activity(), ActivityCompat.requestPermissions(
permissionsToRequest.toTypedArray(), registrar.activity(),
permissionCode) permissionsToRequest.toTypedArray(),
permissionCode)
} else if (mRequestResults.count() > 0) {
processResult()
}
} }
private fun handlePermissionsRequest(permissions: Array<String>, grantResults: IntArray) { private fun handlePermissionsRequest(permissions: Array<String>, grantResults: IntArray) {
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
</value> </value>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">
......
...@@ -6,8 +6,28 @@ ...@@ -6,8 +6,28 @@
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_CALENDAR"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SENSORS" />
<uses-permission android:name="android.permission.BODY_SENSORS" />
<!-- io.flutter.app.FlutterApplication is an android.app.Application that <!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method. calls FlutterMain.startInitialization(this); in its onCreate method.
......
...@@ -13,6 +13,14 @@ class MyApp extends StatelessWidget { ...@@ -13,6 +13,14 @@ class MyApp extends StatelessWidget {
home: new Scaffold( home: new Scaffold(
appBar: new AppBar( appBar: new AppBar(
title: const Text('Plugin example app'), title: const Text('Plugin example app'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
PermissionHandler.openAppSettings();
},
)
],
), ),
body: new Center( body: new Center(
child: new ListView( child: new ListView(
...@@ -20,14 +28,14 @@ class MyApp extends StatelessWidget { ...@@ -20,14 +28,14 @@ class MyApp extends StatelessWidget {
.where((PermissionGroup permission) { .where((PermissionGroup permission) {
if (Platform.isIOS) { if (Platform.isIOS) {
return permission != PermissionGroup.unknown && return permission != PermissionGroup.unknown &&
permission != PermissionGroup.phone && permission != PermissionGroup.phone &&
permission != PermissionGroup.sms && permission != PermissionGroup.sms &&
permission != PermissionGroup.storage; permission != PermissionGroup.storage;
} else { } else {
return permission != PermissionGroup.unknown && return permission != PermissionGroup.unknown &&
permission != PermissionGroup.mediaLibrary && permission != PermissionGroup.mediaLibrary &&
permission != PermissionGroup.photos && permission != PermissionGroup.photos &&
permission != PermissionGroup.reminders; permission != PermissionGroup.reminders;
} }
}) })
.map((PermissionGroup permission) => .map((PermissionGroup permission) =>
...@@ -61,9 +69,12 @@ class _PermissionState extends State<PermissionWidget> { ...@@ -61,9 +69,12 @@ class _PermissionState extends State<PermissionWidget> {
} }
void _listenForPermissionStatus() async { void _listenForPermissionStatus() async {
print(_permissionGroup.toString()); final PermissionStatus status =
_permissionStatus =
await PermissionHandler.checkPermissionStatus(_permissionGroup); await PermissionHandler.checkPermissionStatus(_permissionGroup);
setState(() {
_permissionStatus = status;
});
} }
Color getPermissionColor() { Color getPermissionColor() {
...@@ -86,18 +97,18 @@ class _PermissionState extends State<PermissionWidget> { ...@@ -86,18 +97,18 @@ class _PermissionState extends State<PermissionWidget> {
style: new TextStyle(color: getPermissionColor()), style: new TextStyle(color: getPermissionColor()),
), ),
onTap: () async { onTap: () async {
if (_permissionStatus == PermissionStatus.unknown) { requestPermission(_permissionGroup);
final List<PermissionGroup> permissions = <PermissionGroup>[
_permissionGroup
];
final Map<PermissionGroup, PermissionStatus> permissionRequestResult =
await PermissionHandler.requestPermissions(permissions);
setState(() {
_permissionStatus = permissionRequestResult[_permissionGroup];
});
}
}, },
); );
} }
void requestPermission(PermissionGroup permission) async {
final List<PermissionGroup> permissions = <PermissionGroup>[permission];
final Map<PermissionGroup, PermissionStatus> permissionRequestResult =
await PermissionHandler.requestPermissions(permissions);
setState(() {
_permissionStatus = permissionRequestResult[permission];
});
}
} }
...@@ -8,41 +8,36 @@ ...@@ -8,41 +8,36 @@
import Flutter import Flutter
import Foundation import Foundation
import UIKit import UIKit
import Swift
class PermissionManager: NSObject { class PermissionManager: NSObject {
private var _strategyInstances: [ObjectIdentifier: PermissionStrategy] = [:]
static func checkPermissionStatus(permission: PermissionGroup, result: @escaping FlutterResult) { static func checkPermissionStatus(permission: PermissionGroup, result: @escaping FlutterResult) {
let permissionStrategy = PermissionManager.createPermissionStrategy(permission: permission) let permissionStrategy = PermissionManager.createPermissionStrategy(permission: permission)
let permissionStatus = permissionStrategy?.checkPermissionStatus(permission: permission) ?? PermissionStatus.unknown let permissionStatus = permissionStrategy.checkPermissionStatus(permission: permission)
result(Codec.encodePermissionStatus(permissionStatus: permissionStatus)) result(Codec.encodePermissionStatus(permissionStatus: permissionStatus))
} }
static func requestPermission(permissions: [PermissionGroup], result: @escaping FlutterResult) { func requestPermission(permissions: [PermissionGroup], result: @escaping FlutterResult) {
var requestQueue = Set(permissions.map { $0 }) var requestQueue = Set(permissions.map { $0 })
var permissionStatusResult: [PermissionGroup: PermissionStatus] = [:] var permissionStatusResult: [PermissionGroup: PermissionStatus] = [:]
for permission in permissions { for permission in permissions {
let permissionStrategy = PermissionManager.createPermissionStrategy(permission: permission) let permissionStrategy = PermissionManager.createPermissionStrategy(permission: permission)
let identifier = ObjectIdentifier(permissionStrategy as AnyObject)
if permissionStrategy == nil { _strategyInstances[identifier] = permissionStrategy
permissionStatusResult[permission] = PermissionStatus.unknown
permissionStrategy.requestPermission(permission: permission) { (permissionStatus: PermissionStatus) in
permissionStatusResult[permission] = permissionStatus
requestQueue.remove(permission) requestQueue.remove(permission)
self._strategyInstances.removeValue(forKey: ObjectIdentifier(permissionStrategy as AnyObject))
if requestQueue.count == 0 { if requestQueue.count == 0 {
result(Codec.encodePermissionRequestResult(permissionStatusResult: permissionStatusResult)) result(Codec.encodePermissionRequestResult(permissionStatusResult: permissionStatusResult))
return return
} }
} else {
permissionStrategy!.requestPermission(permission: permission) { (permissionStatus: PermissionStatus) in
permissionStatusResult[permission] = permissionStatus
requestQueue.remove(permission)
if requestQueue.count == 0 {
result(Codec.encodePermissionRequestResult(permissionStatusResult: permissionStatusResult))
return
}
}
} }
} }
} }
...@@ -63,7 +58,7 @@ class PermissionManager: NSObject { ...@@ -63,7 +58,7 @@ class PermissionManager: NSObject {
result(false) result(false)
} }
private static func createPermissionStrategy(permission: PermissionGroup) -> PermissionStrategy? { private static func createPermissionStrategy(permission: PermissionGroup) -> PermissionStrategy {
switch permission { switch permission {
case PermissionGroup.calendar: case PermissionGroup.calendar:
return EventPermissionStrategy() return EventPermissionStrategy()
...@@ -88,7 +83,7 @@ class PermissionManager: NSObject { ...@@ -88,7 +83,7 @@ class PermissionManager: NSObject {
case PermissionGroup.speech: case PermissionGroup.speech:
return SpeechPermissionStrategy() return SpeechPermissionStrategy()
default: default:
return nil return UnknownPermissionStrategy()
} }
} }
} }
...@@ -9,6 +9,7 @@ import UIKit ...@@ -9,6 +9,7 @@ import UIKit
public class SwiftPermissionHandlerPlugin: NSObject, FlutterPlugin { public class SwiftPermissionHandlerPlugin: NSObject, FlutterPlugin {
private static let METHOD_CHANNEL_NAME = "flutter.baseflow.com/permissions/methods"; private static let METHOD_CHANNEL_NAME = "flutter.baseflow.com/permissions/methods";
private let _permissionManager: PermissionManager = PermissionManager()
public static func register(with registrar: FlutterPluginRegistrar) { public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()) let channel = FlutterMethodChannel(name: METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger())
...@@ -23,7 +24,7 @@ public class SwiftPermissionHandlerPlugin: NSObject, FlutterPlugin { ...@@ -23,7 +24,7 @@ public class SwiftPermissionHandlerPlugin: NSObject, FlutterPlugin {
from: call.arguments), from: call.arguments),
result: result) result: result)
} else if call.method == "requestPermissions" { } else if call.method == "requestPermissions" {
PermissionManager.requestPermission( _permissionManager.requestPermission(
permissions: Codec.decodePermissionGroups( permissions: Codec.decodePermissionGroups(
from: call.arguments), from: call.arguments),
result: result) result: result)
......
...@@ -9,6 +9,7 @@ import CoreLocation ...@@ -9,6 +9,7 @@ import CoreLocation
import Foundation import Foundation
class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManagerDelegate { class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManagerDelegate {
private var _locationManager: CLLocationManager? = nil
private var _permissionStatusHandler: PermissionStatusHandler? = nil private var _permissionStatusHandler: PermissionStatusHandler? = nil
private var _requestedPermission: PermissionGroup? = nil private var _requestedPermission: PermissionGroup? = nil
...@@ -40,26 +41,29 @@ class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManag ...@@ -40,26 +41,29 @@ class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManag
_permissionStatusHandler = completionHandler _permissionStatusHandler = completionHandler
_requestedPermission = permission _requestedPermission = permission
let locationManager = CLLocationManager.init()
locationManager.delegate = self
if(permission != PermissionGroup.location) { if(_locationManager == nil) {
if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) { _locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization() _locationManager!.delegate = self
} else if (Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil) { }
locationManager.requestAlwaysAuthorization();
if(permission == PermissionGroup.location) {
if (Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil) {
_locationManager!.requestAlwaysAuthorization()
} else if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) {
_locationManager!.requestWhenInUseAuthorization();
} else { } else {
NSException(name: NSExceptionName.internalInconsistencyException, reason:"To use location in iOS8 you need to define either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in the app bundle's Info.plist file", userInfo: nil).raise() NSException(name: NSExceptionName.internalInconsistencyException, reason:"To use location in iOS8 you need to define either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in the app bundle's Info.plist file", userInfo: nil).raise()
} }
} else if permission == PermissionGroup.locationAlways { } else if permission == PermissionGroup.locationAlways {
if (Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil) { if (Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil) {
locationManager.requestAlwaysAuthorization(); _locationManager!.requestAlwaysAuthorization();
} else { } else {
NSException(name: NSExceptionName.internalInconsistencyException, reason:"To use location in iOS8 you need to define NSLocationAlwaysUsageDescription in the app bundle's Info.plist file", userInfo: nil).raise() NSException(name: NSExceptionName.internalInconsistencyException, reason:"To use location in iOS8 you need to define NSLocationAlwaysUsageDescription in the app bundle's Info.plist file", userInfo: nil).raise()
} }
} else if permission == PermissionGroup.locationWhenInUse { } else if permission == PermissionGroup.locationWhenInUse {
if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) { if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) {
locationManager.requestWhenInUseAuthorization(); _locationManager!.requestWhenInUseAuthorization();
} else { } else {
NSException(name: NSExceptionName.internalInconsistencyException, reason:"To use location in iOS8 you need to define NSLocationWhenInUseUsageDescription in the app bundle's Info.plist file", userInfo: nil).raise() NSException(name: NSExceptionName.internalInconsistencyException, reason:"To use location in iOS8 you need to define NSLocationWhenInUseUsageDescription in the app bundle's Info.plist file", userInfo: nil).raise()
} }
...@@ -67,6 +71,10 @@ class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManag ...@@ -67,6 +71,10 @@ class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManag
} }
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.notDetermined {
return
}
guard let completionHandler = _permissionStatusHandler else { return } guard let completionHandler = _permissionStatusHandler else { return }
completionHandler( completionHandler(
......
...@@ -48,14 +48,13 @@ class SensorPermissionStrategy : NSObject, PermissionStrategy { ...@@ -48,14 +48,13 @@ class SensorPermissionStrategy : NSObject, PermissionStrategy {
if #available(iOS 11.0, *) { if #available(iOS 11.0, *) {
let motionManager = CMMotionActivityManager.init() let motionManager = CMMotionActivityManager.init()
motionManager.queryActivityStarting(from: NSDate.distantPast, to: NSDate.distantFuture, to: OperationQueue.main) { motionManager.startActivityUpdates(to: OperationQueue.main) { (_) in
(results: [CMMotionActivity]?, error: Error?) in motionManager.stopActivityUpdates()
if results != nil {
completionHandler(PermissionStatus.granted) completionHandler(.granted)
} else {
completionHandler(PermissionStatus.denied)
}
} }
} else {
completionHandler(.unknown)
} }
} }
} }
...@@ -38,9 +38,9 @@ class SpeechPermissionStrategy : NSObject, PermissionStrategy { ...@@ -38,9 +38,9 @@ class SpeechPermissionStrategy : NSObject, PermissionStrategy {
SpeechPermissionStrategy.determinePermissionStatus(authorizationStatus: authorizationStatus)) SpeechPermissionStrategy.determinePermissionStatus(authorizationStatus: authorizationStatus))
return return
} }
} else {
completionHandler(PermissionStatus.unknown)
} }
completionHandler(PermissionStatus.unknown)
} }
@available(iOS 10.0, *) @available(iOS 10.0, *)
......
//
// UnknownPermissionStrategy.swift
// permission_handler
//
// Created by Maurits van Beusekom on 07/08/2018.
//
import Foundation
class UnknownPermissionStrategy : NSObject, PermissionStrategy {
func checkPermissionStatus(permission: PermissionGroup) -> PermissionStatus {
return PermissionStatus.unknown
}
func requestPermission(permission: PermissionGroup, completionHandler: @escaping PermissionStatusHandler) {
completionHandler(PermissionStatus.unknown)
}
}
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