Skip to content

Implemented example app #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,14 @@ class PermissionHandlerPlugin(private val registrar: Registrar, private var requ
}
}

ActivityCompat.requestPermissions(
registrar.activity(),
permissionsToRequest.toTypedArray(),
permissionCode)
if (permissionsToRequest.count() > 0) {
ActivityCompat.requestPermissions(
registrar.activity(),
permissionsToRequest.toTypedArray(),
permissionCode)
} else if (mRequestResults.count() > 0) {
processResult()
}
}

private fun handlePermissionsRequest(permissions: Array<String>, grantResults: IntArray) {
Expand Down
Binary file modified example/android/.idea/caches/build_file_checksums.ser
Binary file not shown.
2 changes: 1 addition & 1 deletion example/android/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 22 additions & 2 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,28 @@
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<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
calls FlutterMain.startInitialization(this); in its onCreate method.
Expand Down
85 changes: 69 additions & 16 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,46 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_enums.dart';
import 'package:permission_handler/permission_handler.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {

@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Plugin example app'),
),
body: new Center(
child: new ListView(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Plugin example app'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
PermissionHandler.openAppSettings();
},
)
],
),
body: new Center(
child: new ListView(
children: PermissionGroup.values
.where((PermissionGroup permission) => permission != PermissionGroup.unknown)
.map((PermissionGroup permission) => new PermissionWidget(permission)).toList()
),
.where((PermissionGroup permission) {
if (Platform.isIOS) {
return permission != PermissionGroup.unknown &&
permission != PermissionGroup.phone &&
permission != PermissionGroup.sms &&
permission != PermissionGroup.storage;
} else {
return permission != PermissionGroup.unknown &&
permission != PermissionGroup.mediaLibrary &&
permission != PermissionGroup.photos &&
permission != PermissionGroup.reminders;
}
})
.map((PermissionGroup permission) =>
new PermissionWidget(permission))
.toList()),
),
));
}
Expand All @@ -38,7 +60,7 @@ class _PermissionState extends State<PermissionWidget> {
PermissionStatus _permissionStatus = PermissionStatus.unknown;

_PermissionState(this._permissionGroup);

@override
void initState() {
super.initState();
Expand All @@ -47,15 +69,46 @@ class _PermissionState extends State<PermissionWidget> {
}

void _listenForPermissionStatus() async {
print(_permissionGroup.toString());
_permissionStatus = await PermissionHandler.checkPermissionStatus(_permissionGroup);
final PermissionStatus status =
await PermissionHandler.checkPermissionStatus(_permissionGroup);

setState(() {
_permissionStatus = status;
});
}

Color getPermissionColor() {
switch (_permissionStatus) {
case PermissionStatus.denied:
return Colors.red;
case PermissionStatus.granted:
return Colors.green;
default:
return Colors.grey;
}
}

@override
@override
Widget build(BuildContext context) {
return new ListTile(
title: new Text(_permissionGroup.toString()),
subtitle: new Text(_permissionStatus.toString()),
subtitle: new Text(
_permissionStatus.toString(),
style: new TextStyle(color: getPermissionColor()),
),
onTap: () async {
requestPermission(_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];
});
}
}
29 changes: 12 additions & 17 deletions ios/Classes/PermissionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,36 @@
import Flutter
import Foundation
import UIKit
import Swift

class PermissionManager: NSObject {
private var _strategyInstances: [ObjectIdentifier: PermissionStrategy] = [:]

static func checkPermissionStatus(permission: PermissionGroup, result: @escaping FlutterResult) {
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))
}

static func requestPermission(permissions: [PermissionGroup], result: @escaping FlutterResult) {
func requestPermission(permissions: [PermissionGroup], result: @escaping FlutterResult) {
var requestQueue = Set(permissions.map { $0 })
var permissionStatusResult: [PermissionGroup: PermissionStatus] = [:]

for permission in permissions {
let permissionStrategy = PermissionManager.createPermissionStrategy(permission: permission)

if permissionStrategy == nil {
permissionStatusResult[permission] = PermissionStatus.unknown
let identifier = ObjectIdentifier(permissionStrategy as AnyObject)
_strategyInstances[identifier] = permissionStrategy

permissionStrategy.requestPermission(permission: permission) { (permissionStatus: PermissionStatus) in
permissionStatusResult[permission] = permissionStatus
requestQueue.remove(permission)
self._strategyInstances.removeValue(forKey: ObjectIdentifier(permissionStrategy as AnyObject))

if requestQueue.count == 0 {
result(Codec.encodePermissionRequestResult(permissionStatusResult: permissionStatusResult))
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
}
}
}
}
}
Expand All @@ -63,7 +58,7 @@ class PermissionManager: NSObject {
result(false)
}

private static func createPermissionStrategy(permission: PermissionGroup) -> PermissionStrategy? {
private static func createPermissionStrategy(permission: PermissionGroup) -> PermissionStrategy {
switch permission {
case PermissionGroup.calendar:
return EventPermissionStrategy()
Expand All @@ -88,7 +83,7 @@ class PermissionManager: NSObject {
case PermissionGroup.speech:
return SpeechPermissionStrategy()
default:
return nil
return UnknownPermissionStrategy()
}
}
}
3 changes: 2 additions & 1 deletion ios/Classes/SwiftPermissionHandlerPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import UIKit

public class SwiftPermissionHandlerPlugin: NSObject, FlutterPlugin {
private static let METHOD_CHANNEL_NAME = "flutter.baseflow.com/permissions/methods";
private let _permissionManager: PermissionManager = PermissionManager()

public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger())
Expand All @@ -23,7 +24,7 @@ public class SwiftPermissionHandlerPlugin: NSObject, FlutterPlugin {
from: call.arguments),
result: result)
} else if call.method == "requestPermissions" {
PermissionManager.requestPermission(
_permissionManager.requestPermission(
permissions: Codec.decodePermissionGroups(
from: call.arguments),
result: result)
Expand Down
26 changes: 17 additions & 9 deletions ios/Classes/strategies/LocationPermissionStrategy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import CoreLocation
import Foundation

class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManagerDelegate {
private var _locationManager: CLLocationManager? = nil
private var _permissionStatusHandler: PermissionStatusHandler? = nil
private var _requestedPermission: PermissionGroup? = nil

Expand Down Expand Up @@ -40,33 +41,40 @@ class LocationPermissionStrategy : NSObject, PermissionStrategy, CLLocationManag

_permissionStatusHandler = completionHandler
_requestedPermission = permission
let locationManager = CLLocationManager.init()
locationManager.delegate = self

if(permission != PermissionGroup.location) {
if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) {
locationManager.requestWhenInUseAuthorization()
} else if (Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil) {
locationManager.requestAlwaysAuthorization();
if(_locationManager == nil) {
_locationManager = CLLocationManager()
_locationManager!.delegate = self
}

if(permission == PermissionGroup.location) {
if (Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil) {
_locationManager!.requestAlwaysAuthorization()
} else if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) {
_locationManager!.requestWhenInUseAuthorization();
} 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()
}
} else if permission == PermissionGroup.locationAlways {
if (Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil) {
locationManager.requestAlwaysAuthorization();
_locationManager!.requestAlwaysAuthorization();
} 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()
}
} else if permission == PermissionGroup.locationWhenInUse {
if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) {
locationManager.requestWhenInUseAuthorization();
_locationManager!.requestWhenInUseAuthorization();
} 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()
}
}
}

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.notDetermined {
return
}

guard let completionHandler = _permissionStatusHandler else { return }

completionHandler(
Expand Down
13 changes: 6 additions & 7 deletions ios/Classes/strategies/SensorPermissionStrategy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,13 @@ class SensorPermissionStrategy : NSObject, PermissionStrategy {
if #available(iOS 11.0, *) {
let motionManager = CMMotionActivityManager.init()

motionManager.queryActivityStarting(from: NSDate.distantPast, to: NSDate.distantFuture, to: OperationQueue.main) {
(results: [CMMotionActivity]?, error: Error?) in
if results != nil {
completionHandler(PermissionStatus.granted)
} else {
completionHandler(PermissionStatus.denied)
}
motionManager.startActivityUpdates(to: OperationQueue.main) { (_) in
motionManager.stopActivityUpdates()

completionHandler(.granted)
}
} else {
completionHandler(.unknown)
}
}
}
4 changes: 2 additions & 2 deletions ios/Classes/strategies/SpeechPermissionStrategy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class SpeechPermissionStrategy : NSObject, PermissionStrategy {
SpeechPermissionStrategy.determinePermissionStatus(authorizationStatus: authorizationStatus))
return
}
} else {
completionHandler(PermissionStatus.unknown)
}

completionHandler(PermissionStatus.unknown)
}

@available(iOS 10.0, *)
Expand Down
18 changes: 18 additions & 0 deletions ios/Classes/strategies/UnknownPermissionStrategy.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// 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)
}
}