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 permissions; final List permissionNames; final String permissionDesc; ///是否需要强制授予 final bool isRequiredPermission; @override State createState() => _PermissionRequestPageState(); } class _PermissionRequestPageState extends State with WidgetsBindingObserver { bool _isGoSetting = false; late final List 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 permissions) async { ///一个新待申请权限列表 List 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 _requestPermission(List permissions) async { Log.d('_requestPermission permissions=$permissions'); MapEntry? 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); } } }