// Author: fengshengxiong // Date: 2024/5/10 // Description: 权限处理 import 'dart:io'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:tone_snap/components/dialog/remind_dialog.dart'; class PermissionUtil { /// 检测是否有权限 /// [permissionList] 权限申请列表 static Future checkPermission(List permissionList, {bool showDialog = true}) async { // 一个新待申请权限列表 List newPermissionList = []; // 遍历当前权限申请列表 for (Permission permission in permissionList) { PermissionStatus status = await permission.status; // 如果不是允许状态就添加到新的申请列表中 if (!status.isGranted) { newPermissionList.add(permission); } } // 如果需要重新申请的列表不是空的 if (newPermissionList.isNotEmpty) { PermissionStatus permissionStatus = await _requestPermission(newPermissionList); switch (permissionStatus) { // 拒绝状态 case PermissionStatus.denied: if (showDialog) _showFailedDialog(newPermissionList); return false; // 允许状态 case PermissionStatus.granted: case PermissionStatus.limited: return true; // 永久拒绝 case PermissionStatus.provisional: case PermissionStatus.restricted: case PermissionStatus.permanentlyDenied: if (showDialog) _showFailedDialog(newPermissionList, isPermanentlyDenied: true); break; } } else { return true; } return false; } /// 获取新列表中的权限 如果有一项不合格就返回false static Future _requestPermission(List permissionList) async { Map statuses = await permissionList.request(); PermissionStatus currentPermissionStatus = PermissionStatus.granted; statuses.forEach((key, value) { if (!value.isGranted || !value.isLimited) { currentPermissionStatus = value; return; } }); return currentPermissionStatus; } /// 请求位置权限 static Future checkLocationAlways() async { // 获取前置状态 // Android没有这一步 ios会先访问这个再访问其他的 PermissionStatus status1 = PermissionStatus.granted; status1 = await _checkSinglePermission(Permission.locationWhenInUse); // 获取第二个状态 PermissionStatus status2 = PermissionStatus.denied; // 如果前置状态为成功才能执行获取第二个状态 if (status1.isGranted) { status2 = await _checkSinglePermission(Permission.locationAlways); } // 如果两个都成功那么就返回成功 if (status1.isGranted && status2.isGranted) { return true; } else { // 如果有一个拒绝那么就失败了 _showFailedDialog([Permission.locationWhenInUse, Permission.locationAlways], isPermanentlyDenied: Platform.isIOS ? true : false, ); } return false; } /// 请求单个权限 static _checkSinglePermission(Permission permission) async { // 获取当前状态 PermissionStatus status = await permission.status; PermissionStatus currentPermissionStatus = PermissionStatus.granted; // 如果它状态不是允许那么就去获取 if (!status.isGranted) { currentPermissionStatus = await _requestPermission([permission]); } // 返回最终状态 return currentPermissionStatus; } /// 权限拒绝后弹窗 static _showFailedDialog(List permissionList, {bool isPermanentlyDenied = false}) async { Get.dialog( barrierDismissible: false, RemindDialog( content: await _getDescription(permissionList), confirmText: isPermanentlyDenied ? 'Go open' : 'Confirm', confirmOnTap: () { if (isPermanentlyDenied) { openAppSettings(); } else { checkPermission(permissionList); } }, ), ); } /// 获取权限描述 static Future _getDescription(List permissionList) async { late Permission failedPermission; for (Permission permission in permissionList) { if (!await permission.status.isGranted) { failedPermission = permission; break; } } String description = ''; if (failedPermission == Permission.microphone) { description = 'We need to access the microphone to record or select audio files.'; } else if (failedPermission == Permission.storage) { description = 'We need to access external storage to select audio files.'; } else if (failedPermission == Permission.audio) { description = 'We need to access external storage to select audio files.'; } else if (failedPermission == Permission.photos) { description = 'We need access to the photo library to pick audio files.'; } else if (failedPermission == Permission.mediaLibrary) { description = 'We need to access the device media library to select audio files.'; } else if (failedPermission == Permission.appTrackingTransparency) { description = 'We need your permission to access the advertising identifier to provide better ad services.'; } return description; } }