permission_request.dart 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import 'dart:io';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:permission_handler/permission_handler.dart';
  5. /// 权限检查及请求
  6. /// 外部可通过此方法来进行权限的检查和请求,将自动跳转到`PermissionRequestPage`页面。
  7. /// 传入 `Permission` 以及对应的权限名称 `permissionTypeStr`,如果有权限则返回 `Future true`
  8. /// `isRequiredPermission` 如果为 `true`,则 "取消" 按钮将执行 "退出app" 的操作
  9. Permission permission = Permission.notification;
  10. Future<bool> permissionCheckAndRequest(
  11. BuildContext context, String permissionTypeStr,
  12. {bool isRequiredPermission = false}) async {
  13. final navigator = Navigator.of(context);
  14. try {
  15. PermissionStatus status = await permission.status;
  16. if (!status.isGranted) {
  17. await navigator.push(PageRouteBuilder(
  18. opaque: false,
  19. pageBuilder: ((context, animation, secondaryAnimation) {
  20. return PermissionRequestPage(permission, permissionTypeStr,
  21. isRequiredPermission: isRequiredPermission);
  22. })));
  23. } else {
  24. return true;
  25. }
  26. return false;
  27. } catch (e) {
  28. return true;
  29. }
  30. }
  31. class PermissionRequestPage extends StatefulWidget {
  32. const PermissionRequestPage(this.permission, this.permissionTypeStr,
  33. {super.key, this.isRequiredPermission = false});
  34. final Permission permission;
  35. final String permissionTypeStr;
  36. final bool isRequiredPermission;
  37. @override
  38. State<PermissionRequestPage> createState() => _PermissionRequestPageState();
  39. }
  40. class _PermissionRequestPageState extends State<PermissionRequestPage>
  41. with WidgetsBindingObserver {
  42. bool _isGoSetting = false;
  43. late final List<String> msgList;
  44. @override
  45. void initState() {
  46. super.initState();
  47. WidgetsBinding.instance.addObserver(this);
  48. msgList = [
  49. "${widget.permissionTypeStr}功能需要获取您设备的${widget.permissionTypeStr}权限,否则可能无法正常工作。\n是否申请${widget.permissionTypeStr}权限?",
  50. "${widget.permissionTypeStr}权限不全,是否重新申请权限?",
  51. "没有${widget.permissionTypeStr}权限,您可以手动开启权限",
  52. widget.isRequiredPermission ? "退出应用" : "取消"
  53. ];
  54. checkPermission(widget.permission);
  55. }
  56. @override
  57. void didChangeAppLifecycleState(AppLifecycleState state) {
  58. super.didChangeAppLifecycleState(state);
  59. // 监听 app 从后台切回前台
  60. if (state == AppLifecycleState.resumed && _isGoSetting) {
  61. checkPermission(widget.permission);
  62. }
  63. }
  64. /// 校验权限
  65. void checkPermission(Permission permission) async {
  66. final status = await permission.status;
  67. if (status.isGranted) {
  68. _popPage();
  69. return;
  70. }
  71. // 还未申请权限或之前拒绝了权限(在 iOS 上为首次申请权限,拒绝后将变为 `永久拒绝权限`)
  72. if (status.isDenied) {
  73. showAlert(
  74. permission, msgList[0], msgList[3], _isGoSetting ? "前往应用中心" : "确定");
  75. }
  76. // 权限已被永久拒绝
  77. if (status.isPermanentlyDenied) {
  78. _isGoSetting = true;
  79. showAlert(
  80. permission, msgList[2], msgList[3], _isGoSetting ? "前往应用中心" : "确定");
  81. }
  82. // 拥有部分权限
  83. if (status.isLimited) {
  84. if (Platform.isIOS || Platform.isMacOS) _isGoSetting = true;
  85. showAlert(
  86. permission, msgList[1], msgList[3], _isGoSetting ? "前往应用中心" : "确定");
  87. }
  88. // 拥有部分权限(仅限 iOS)
  89. if (status.isRestricted) {
  90. if (Platform.isIOS || Platform.isMacOS) _isGoSetting = true;
  91. showAlert(
  92. permission, msgList[1], msgList[3], _isGoSetting ? "前往应用中心" : "确定");
  93. }
  94. }
  95. void showAlert(Permission permission, String message, String cancelMsg,
  96. String confirmMsg) {
  97. showCupertinoDialog(
  98. context: context,
  99. builder: (context) {
  100. return CupertinoAlertDialog(
  101. title: const Text("温馨提示"),
  102. content: Text(message),
  103. actions: [
  104. CupertinoDialogAction(
  105. child: Text(cancelMsg),
  106. onPressed: () {
  107. widget.isRequiredPermission
  108. ? _quitApp()
  109. : _popDialogAndPage(context);
  110. }),
  111. CupertinoDialogAction(
  112. child: Text(confirmMsg),
  113. onPressed: () {
  114. if (_isGoSetting) {
  115. openAppSettings();
  116. _isGoSetting = true;
  117. } else {
  118. requestPermisson(permission);
  119. }
  120. _popDialog(context);
  121. })
  122. ],
  123. );
  124. });
  125. }
  126. /// 申请权限
  127. void requestPermisson(Permission permission) async {
  128. // 申请权限
  129. await permission.request();
  130. // 再次校验
  131. checkPermission(permission);
  132. }
  133. @override
  134. void dispose() {
  135. WidgetsBinding.instance.removeObserver(this);
  136. super.dispose();
  137. }
  138. @override
  139. Widget build(BuildContext context) {
  140. return Container();
  141. }
  142. /// 退出应用程序
  143. void _quitApp() {
  144. SystemChannels.platform.invokeMethod("SystemNavigator.pop");
  145. }
  146. /// 关闭整个权限申请页面
  147. void _popDialogAndPage(BuildContext dialogContext) {
  148. _popDialog(dialogContext);
  149. _popPage();
  150. }
  151. /// 关闭弹窗
  152. void _popDialog(BuildContext dialogContext) {
  153. Navigator.of(dialogContext).pop();
  154. }
  155. /// 关闭透明页面
  156. void _popPage() {
  157. Navigator.of(context).pop();
  158. }
  159. }