permissionRequestPage.dart
8.1 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
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:wow_english/common/core/app_config_helper.dart';
import 'package:wow_english/common/permission/permissionRequester.dart';
import '../../utils/log_util.dart';
///带有隐私合规弹窗的透明权限申请页面,主要应对android各大应用市场对隐私权限申请需同步告知索取权限目的
class PermissionRequestPage extends StatefulWidget {
const PermissionRequestPage(this.permissions,
this.permissionNames, this.permissionDesc,
{super.key, this.isRequiredPermission = false});
final List<Permission> permissions;
final List<String> permissionNames;
final String permissionDesc;
///是否需要强制授予
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 permissionDesc = widget.permissionDesc;
String permissionStr = widget.permissionNames.join('、');
msgList = [
"$permissionDesc,需要获取您设备的$permissionStr权限",
"你还没有开启$permissionStr权限,开启后即可$permissionDesc",
"未开启$permissionStr权限导致功能受限,您可以手动开启权限",
widget.isRequiredPermission ? "退出应用" : "以后再说"
];
_handlePermission(widget.permissions);
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
// PackageInfo packageInfo = await PackageInfo.fromPlatform();
// String packageName = packageInfo.packageName;
return Scaffold(
backgroundColor: Colors.transparent,
body: Align(
alignment: Alignment.topCenter,
child: Container(
width: screenWidth / 2,
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10.0), // 圆角半径
boxShadow: const [
BoxShadow(
color: Colors.black26,
blurRadius: 4.0,
offset: Offset(2, 2),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Text(
'${widget.permissionNames.join('、')}权限使用说明',
style: TextStyle(
color: Colors.black,
fontSize: 15.sp,
fontWeight: FontWeight.w500,
fontFamily: 'PingFangSC-Regular'),
textAlign: TextAlign.left,
),
),
16.verticalSpace,
Text(
widget.permissionDesc,
style: const TextStyle(color: Colors.black54,
fontFamily: 'PingFangSC-Regular'),
textAlign: TextAlign.left,
),
],
))));
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
Log.d("didChangeAppLifecycleState state=$state _isGoSetting=$_isGoSetting");
// 监听 app 从后台切回前台
if (state == AppLifecycleState.resumed && _isGoSetting && !_isDialogShowing) {
_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');
MapEntry<Permission, PermissionStatus>? statusEntry =
await requestPermissionsInner(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 ? "前往系统设置" : "继续");
}
// isLimited:拥有部分权限(受限,仅在 iOS (iOS14+) 上受支持)
// isRestricted:拥有部分权限,活动限制(例如,设置了家长///控件,仅在iOS以上受支持。(仅限 iOS)
if (status.isLimited || 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()
: _popDialog(context, false);
}),
TextButton(
child: Text(confirmMsg),
onPressed: () {
if (_isGoSetting) {
openAppSettings();
} else {
_handlePermission(widget.permissions);
}
_popDialog(context, null);
})
],
);
}).then((value) => {
_isDialogShowing = false,
_popPage(value)
});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
/// 退出应用程序
void _quitApp() {
AppConfigHelper.exitApp();
}
/// 关闭弹窗
/// isAllGranted为null的话跳到系统设置页
void _popDialog(BuildContext dialogContext, bool? isAllGranted) {
Navigator.of(dialogContext).pop();
_popPage(isAllGranted);
}
/// 关闭权限申请透明页面
/// isAllGranted 所有权限都授予,为空不关闭
void _popPage(bool? isAllGranted) {
if (isAllGranted != null) {
Navigator.of(context).pop(isAllGranted);
}
}
}