permissionRequestPage.dart
8.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:wow_english/common/core/app_config_helper.dart';
import '../../utils/log_util.dart';
/// 带隐私合规功能的权限检查及请求
/// 外部可通过此方法来进行权限的检查和请求,将自动跳转到`PermissionRequestPage`页面。
/// 传入 `Permission` 以及对应的权限名称 `permissionTypeStr`,如果有权限则返回 `Future true`
/// `isRequiredPermission` 如果为 `true`,则 "取消" 按钮将执行 "退出app" 的操作
Future<bool> permissionCheckAndRequests(
BuildContext context,
List<Permission> permissions,
List<String> permissionTypeStrs,
{bool isRequiredPermission = false}) async {
// List<PermissionStatus> statuses = await Future.wait(
// permissions.map((permission) => permission.status),
// );
// bool allGranted = statuses.every((status) => status.isGranted);
bool allGranted = await isPermissionsGranted(permissions);
if (allGranted) {
return true;
} else {
return await Navigator.of(context).push(PageRouteBuilder(
opaque: false,
pageBuilder: ((context, animation, secondaryAnimation) {
return PermissionRequestPage(permissions, permissionTypeStrs,
isRequiredPermission: isRequiredPermission);
})));
}
}
Future<bool> permissionCheckAndRequest(
BuildContext context,
Permission permission,
String permissionTypeStr,
{bool isRequiredPermission = false}) async {
return permissionCheckAndRequests(context, [permission], [permissionTypeStr],
isRequiredPermission: isRequiredPermission);
}
///判断权限数组是否都授予
Future<bool> isPermissionsGranted(List<Permission> permissions) async {
// 使用 every 直接检查权限状态
return await Future.wait(permissions.map((permission) async {
return await permission.status.isGranted;
})).then((statuses) => statuses.every((status) => status));
}
///请求权限
Future<MapEntry<Permission, PermissionStatus>?> requestPermissions(List<Permission> permissionList) async {
Map<Permission, PermissionStatus> statusesMap = await permissionList.request();
for (var entry in statusesMap.entries) {
if (!entry.value.isGranted) {
return entry;
}
}
return null;
}
class PermissionRequestPage extends StatefulWidget {
const PermissionRequestPage(this.permissions, this.permissionTypeStrs,
{super.key, this.isRequiredPermission = false});
final List<Permission> permissions;
final List<String> permissionTypeStrs;
///是否需要强制授予
final bool isRequiredPermission;
@override
State<PermissionRequestPage> createState() => _PermissionRequestPageState();
}
class _PermissionRequestPageState extends State<PermissionRequestPage>
with WidgetsBindingObserver {
bool _isGoSetting = false;
late final List<String> msgList;
bool _isDialogShowing = false;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
String permissionTypeStrs = widget.permissionTypeStrs.join('、');
msgList = [
"Wow English需要获取您设备的$permissionTypeStrs权限,否则可能无法正常工作。\n是否同意授予?",
"$permissionTypeStrs权限不全,是否重新申请权限?",
"没有$permissionTypeStrs权限,您可以手动开启权限",
widget.isRequiredPermission ? "退出应用" : "取消"
];
_handlePermission(widget.permissions);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
Log.d("didChangeAppLifecycleState state=$state _isGoSetting=$_isGoSetting");
// 监听 app 从后台切回前台
if (state == AppLifecycleState.resumed && _isGoSetting) {
_handlePermission(widget.permissions);
}
}
/// 校验权限
void _handlePermission(List<Permission> permissions) async {
///一个新待申请权限列表
List<Permission> intentPermissionList = [];
///遍历当前权限申请列表
for (Permission permission in permissions) {
PermissionStatus status = await permission.status;
///如果不是允许状态就添加到新的申请列表中
if (!status.isGranted) {
intentPermissionList.add(permission);
}
}
if (intentPermissionList.isEmpty) {
_popPage(true);
} else {
_requestPermission(intentPermissionList);
}
}
///实际触发请求权限
Future<void> _requestPermission(List<Permission> permissions) async {
Log.d('_requestPermission permissions=$permissions');
if (await isPermissionsGranted(permissions)) {
_popPage(true);
return;
}
MapEntry<Permission, PermissionStatus>? statusEntry = await requestPermissions(permissions);
if (statusEntry == null) {
///都手动同意授予了
_popPage(true);
return;
}
Permission permission = statusEntry.key;
PermissionStatus status = statusEntry.value;
// 还未申请权限或之前拒绝了权限(在 iOS 上为首次申请权限,拒绝后将变为 `永久拒绝权限`)
if (status.isDenied) {
showAlert(
permission, msgList[0], msgList[3], _isGoSetting ? "前往系统设置" : "确定");
}
// 权限已被永久拒绝
/// 在 Android 上:Android 11+ (API 30+):用户是否第二次拒绝权限。低于 Android 11 (API 30):用户是否拒绝访问请求的功能,并选择不再显示请求。
/// 在 iOS 上:如果用户拒绝访问所请求的功能。
if (status.isPermanentlyDenied) {
_isGoSetting = true;
showAlert(
permission, msgList[2], msgList[3], _isGoSetting ? "前往系统设置" : "确定");
}
// 拥有部分权限(受限,仅在 iOS (iOS14+) 上受支持)
if (status.isLimited) {
if (Platform.isIOS || Platform.isMacOS) _isGoSetting = true;
showAlert(
permission, msgList[1], msgList[3], _isGoSetting ? "前往系统设置" : "确定");
}
// 拥有部分权限,活动限制(例如,设置了家长///控件,仅在iOS以上受支持。(仅限 iOS)
if (status.isRestricted) {
if (Platform.isIOS || Platform.isMacOS) _isGoSetting = true;
showAlert(
permission, msgList[1], msgList[3], _isGoSetting ? "前往系统设置" : "确定");
}
}
void showAlert(Permission permission, String message, String cancelMsg,
String confirmMsg) {
if (_isDialogShowing) {
// 对话框已经在显示中,不重复弹出
Log.d("对话框已经在显示中,不重复弹出");
return;
}
_isDialogShowing = true;
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("温馨提示"),
content: Text(message),
actions: [
TextButton(
child: Text(cancelMsg),
onPressed: () {
widget.isRequiredPermission
? _quitApp()
: _popDialogAndPage(context, false);
}),
TextButton(
child: Text(confirmMsg),
onPressed: () {
if (_isGoSetting) {
openAppSettings();
} else {
_handlePermission(widget.permissions);
}
_popDialog(context);
})
],
);
}).then((value) => {
_isDialogShowing = false,
});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
/// 退出应用程序
void _quitApp() {
AppConfigHelper.exitApp();
}
/// 关闭整个权限申请页面
void _popDialogAndPage(BuildContext dialogContext, bool isAllGranted) {
_popDialog(dialogContext);
_popPage(isAllGranted);
}
/// 关闭弹窗
void _popDialog(BuildContext dialogContext) {
Navigator.of(dialogContext).pop();
}
/// 关闭透明页面
void _popPage(bool isAllGranted) {
Navigator.of(context).pop(isAllGranted);
}
}