Skip to content

Commit e40a6b0

Browse files
committed
Add context to callback, add readme
1 parent 215113b commit e40a6b0

File tree

4 files changed

+138
-41
lines changed

4 files changed

+138
-41
lines changed

README.md

Lines changed: 132 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
11
# flutter-force-permission
2+
23
[![codecov](https://codecov.io/gh/gogovan/flutter-force-permission/branch/main/graph/badge.svg?token=F9DPJUAVAJ)](https://codecov.io/gh/gogovan/flutter-force-permission)
34

4-
Show permission disclosure page and allows required permissions and their associated services before the user can proceed.
5+
Show permission disclosure page and allows required permissions and their associated services before
6+
the user can proceed.
57

6-
This package shows a prominent in-app disclosure page for getting permissions as required by [Google Play](https://support.google.com/googleplay/android-developer/answer/9799150?visit_id=638041800350153935-369621111&p=pd-m&rd=1#prominent_disclosure&zippy=%2Cstep-provide-prominent-in-app-disclosure%2Cstep-review-best-practices-for-accessing-location%2Cstep-consider-alternatives-to-accessing-location-in-the-background%2Cstep-make-access-to-location-in-the-background-clear-to-users%2Csee-an-example-of-prominent-in-app-disclosure).
7-
Also support iOS to ensure a consistent experience.
8+
This package shows a prominent in-app disclosure page for getting permissions as required
9+
by [Google Play](https://support.google.com/googleplay/android-developer/answer/9799150?visit_id=638041800350153935-369621111&p=pd-m&rd=1#prominent_disclosure&zippy=%2Cstep-provide-prominent-in-app-disclosure%2Cstep-review-best-practices-for-accessing-location%2Cstep-consider-alternatives-to-accessing-location-in-the-background%2Cstep-make-access-to-location-in-the-background-clear-to-users%2Csee-an-example-of-prominent-in-app-disclosure)
10+
. Also support iOS to ensure a consistent experience.
811

9-
In addition, permissions and their associated services (e.g. GPS) can be set as "required". If this is set, those required permissions will
10-
be required and if users denied it, this package will show a customizable dialog and redirect user to the appropriate settings page provided by the native OS.
12+
In addition, permissions and their associated services (e.g. GPS) can be set as "required". If this
13+
is set, those required permissions will be required and if users denied it, this package will show a
14+
customizable dialog and redirect user to the appropriate settings page provided by the native OS.
1115

1216
## Setup
17+
1318
1. Add the following to `pubspec.yaml`
19+
1420
```yaml
1521
dependencies:
1622
flutter_force_permission: ^0.1.0
1723
permission_handler: ^10.2.0
1824
```
19-
2. This package depends on [permission_handler](https://pub.dev/packages/permission_handler). Perform setup according to that package.
20-
3. On Android, if you use `POST_NOTIFICATIONS` permission, update the `targetSdkVersion` in `build.gradle` to at least 33 so that the permission request dialog is shown correctly. Refer to [relevant Android Developer page](https://developer.android.com/develop/ui/views/notifications/notification-permission) for details.
25+
26+
2. This package depends on [permission_handler](https://pub.dev/packages/permission_handler).
27+
Perform setup according to that package.
28+
3. On Android, if you use `POST_NOTIFICATIONS` permission, update the `targetSdkVersion`
29+
in `build.gradle` to at least 33 so that the permission request dialog is shown correctly. Refer
30+
to [relevant Android Developer page](https://developer.android.com/develop/ui/views/notifications/notification-permission)
31+
for details.
32+
2133
```groovy
2234
android {
2335
// ...
@@ -29,53 +41,135 @@ android {
2941
// ...
3042
}
3143
```
32-
4. If any features is required, it is highly recommended to also set the `<uses-feature>` tag in AndroidManifest.xml. Refer to [relevant Android Developers page](https://developer.android.com/guide/topics/manifest/uses-feature-element) for details.
44+
45+
4. If any features is required, it is highly recommended to also set the `<uses-feature>` tag in
46+
AndroidManifest.xml. Refer
47+
to [relevant Android Developers page](https://developer.android.com/guide/topics/manifest/uses-feature-element)
48+
for details.
3349

3450
## Usage
35-
1. Create an instance of FlutterForcePermission, providing configuration. Refer to documentation for [FlutterForcePermissionConfig] for details.
51+
52+
1. Create an instance of FlutterForcePermission, providing configuration. Refer to documentation
53+
for [FlutterForcePermissionConfig] for details.
54+
3655
```dart
56+
3757
final perm = FlutterForcePermission(
38-
FlutterForcePermissionConfig(
39-
title: 'Title',
40-
permissionItemConfigs: [
41-
PermissionItemConfig(
42-
permissions: [Permission.locationWhenInUse],
43-
required: true,
44-
itemText: PermissionItemText(
45-
header: 'Foreground Location',
46-
rationaleText: 'Rationale for Foreground location. Required.',
47-
forcedPermissionDialogConfig: ForcedPermissionDialogConfig(
48-
title: 'Please enable location permission',
49-
text: 'Please enable location permission for proper usage.',
50-
buttonText: 'Settings',
51-
),
58+
FlutterForcePermissionConfig(
59+
title: 'Title',
60+
permissionItemConfigs: [
61+
PermissionItemConfig(
62+
permissions: [Permission.locationWhenInUse],
63+
required: true,
64+
itemText: PermissionItemText(
65+
header: 'Foreground Location',
66+
rationaleText: 'Rationale for Foreground location. Required.',
67+
forcedPermissionDialogConfig: ForcedPermissionDialogConfig(
68+
title: 'Please enable location permission',
69+
text: 'Please enable location permission for proper usage.',
70+
buttonText: 'Settings',
5271
),
5372
),
54-
PermissionItemConfig(
55-
permissions: [Permission.locationAlways],
56-
itemText: PermissionItemText(
57-
header: 'Background Location',
58-
rationaleText: 'Rationale for Background location. lorem ipsum dolor sit amet.',
59-
),
73+
),
74+
PermissionItemConfig(
75+
permissions: [Permission.locationAlways],
76+
itemText: PermissionItemText(
77+
header: 'Background Location',
78+
rationaleText: 'Rationale for Background location. lorem ipsum dolor sit amet.',
6079
),
61-
],
62-
),
63-
);
80+
),
81+
],
82+
),
83+
);
6484
```
65-
2. Show the disclosure page as needed. This method will handle showing the disclosure page and requesting permissions.
66-
This function takes a [NavigatorState](https://api.flutter.dev/flutter/widgets/NavigatorState-class.html) which can be retrieved through `Navigator.of(context)` call.
67-
This is an async function. Wrap the function in an `async` block as needed.
68-
Returns a map of permission and their requested status (granted/denied/etc), service status and whether they are requested by this plugin.
85+
86+
2. Show the disclosure page as needed. This method will handle showing the disclosure page and
87+
requesting permissions. This function takes
88+
a [NavigatorState](https://api.flutter.dev/flutter/widgets/NavigatorState-class.html) which can
89+
be retrieved through `Navigator.of(context)` call. This is an async function. Wrap the function
90+
in an `async` block as needed. Returns a map of permission and their requested status (
91+
granted/denied/etc), service status and whether they are requested by this plugin.
92+
6993
```dart
70-
final result = await perm.show(Navigator.of(context));
94+
95+
final result = await
96+
perm.show(Navigator.of(context));
7197
```
7298

7399
### Styling
74-
You can set the style of the text shown by setting up a [TextTheme](https://api.flutter.dev/flutter/material/TextTheme-class.html) of the provided context.
100+
101+
You can set the style of the text shown by setting up
102+
a [TextTheme](https://api.flutter.dev/flutter/material/TextTheme-class.html) of the provided
103+
context.
104+
75105
- Title uses `headline6` text style.
76106
- Item header use `subtitle1` text style.
77107
- Item body use `bodyText2` text style.
78108

109+
## Advanced Usage
110+
111+
### Customize the required permission denied prompt
112+
113+
If you wish to customize the dialog shown when the required permission is denied, provide
114+
a `showDialogCallback` which to show your dialog. Parameters are included for you to compose the
115+
appropriate dialog. In your callback, you SHOULD:
116+
117+
1. Display a non-dismissable dialog. This can be typically achieved by setting `barrierDismissible`
118+
to false and provide an empty callback e.g. (`() async => false`) to `willPopCallback` for your
119+
dialog.
120+
2. Call the provided `callback` parameter in your callback when the user click the confirm button,
121+
and dismiss your dialog by `Navigator.pop`.
122+
123+
```dart
124+
125+
final config = FlutterForcePermissionConfig(
126+
title: 'Title',
127+
confirmText: 'Confirm',
128+
permissionItemConfigs: [
129+
PermissionItemConfig(
130+
permissions: [
131+
Permission.location,
132+
],
133+
itemText: PermissionItemText(
134+
header: 'Foreground location',
135+
rationaleText: 'Rationale',
136+
forcedPermissionDialogConfig: ForcedPermissionDialogConfig(
137+
title: 'Location required',
138+
text: 'Location needed for proper operation',
139+
buttonText: 'Settings',
140+
),
141+
),
142+
required: true,
143+
),
144+
],
145+
showDialogCallback: (context, title, text, button, callback) {
146+
// Store the navigator to avoid storing contexts across async gaps. See https://stackoverflow.com/a/69512692/11675817 for details.
147+
final navigator = Navigator.of(context);
148+
// Show your dialog.
149+
showDialog(context: context,
150+
barrierDismissible: false,
151+
builder: (context) =>
152+
WillPopScope(
153+
onWillPop: () async => false,
154+
child: AlertDialog(
155+
title: Text(title),
156+
content: Text(text),
157+
actions: [
158+
TextButton(
159+
onPressed: () {
160+
callback();
161+
navigator.pop();
162+
},
163+
child: Text(button),
164+
),
165+
],
166+
),
167+
),
168+
);
169+
},
170+
);
171+
```
172+
79173
## Issues
80174

81175
## Contributing

lib/flutter_force_permission_config.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ library flutter_force_permission;
33
import 'package:flutter/material.dart';
44
import 'package:flutter_force_permission/permission_item_config.dart';
55

6-
typedef ShowDialogCallback = void Function(String title, String content, String buttonText, VoidCallback callback);
6+
typedef ShowDialogCallback = void Function(BuildContext context, String title, String content, String buttonText, VoidCallback callback);
77

88
/// Configuration for Flutter Force Permission.
99
class FlutterForcePermissionConfig {
@@ -32,9 +32,11 @@ class FlutterForcePermissionConfig {
3232
/// as `title`, `content` and the confirm button `buttonText` respectively, as well
3333
/// as a `callback` for you to call when the confirm button is clicked.
3434
///
35-
/// This callback SHOULD invoke the provided `callback` in your callback to ensure proper functionality by invoking system OS settings.
35+
/// This callback SHOULD invoke the provided `callback` in your callback upon confirmation
36+
/// to ensure proper functionality as the `callback` will invoke appropriate setting pages provided by the OS.
3637
/// The dialog shown during your callback SHOULD NOT be dismissable. It is typically
3738
/// achieved by setting `barrierDismissible` to false and provide an empty callback
3839
/// e.g. (`() async => false`) to `willPopCallback` for your dialog.
40+
/// Also, you will probably need to dismiss your dialog after confirmation.
3941
final ShowDialogCallback? showDialogCallback;
4042
}

lib/src/views/disclosure_page.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ class _DisclosurePageState extends State<DisclosurePage>
302302
);
303303
} else {
304304
callback(
305+
context,
305306
dialogConfig?.title ?? '',
306307
dialogConfig?.text ?? '',
307308
dialogConfig?.buttonText ?? '',

test/widget_test/disclosure_page_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ void main() {
443443
required: true,
444444
),
445445
],
446-
showDialogCallback: (title, text, button, callback) {
446+
showDialogCallback: (context, title, text, button, callback) {
447447
callback();
448448
},
449449
);

0 commit comments

Comments
 (0)