Files
2026-09-15 15:44:13 +07:00

80 lines
3.5 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:hgdj/tools_base/widget/common_alert.dart';
import 'package:permission_handler/permission_handler.dart';
import '../tools_base/toast.dart';
class PermissionUtil {
static Future<bool> checkPhotoPermission() async {
final Permission permission;
if (Platform.isIOS || Platform.isMacOS) {
permission = Permission.photos;
} else {
final androidInfo = await DeviceInfoPlugin().androidInfo;
// 按 API 级别(sdkInt)判断:Android 13(API 33)起用照片权限,以下用存储权限。
// 不能用 version.release(营销版本号字符串,ROM 可能写成 "12L" 等致解析跑偏)
permission = androidInfo.version.sdkInt < 33
? Permission.storage
: Permission.photos;
}
return _ensure(permission, '需要相册权限才能继续');
}
static Future<bool> checkPhotoAddOnlyPermission() async {
final permission = (Platform.isIOS || Platform.isMacOS)
? Permission.photosAddOnly
: Permission.storage;
return _ensure(permission, '需要相册权限才能继续');
}
static Future<bool> checkCameraPermission() async {
return _ensure(Permission.camera, '需要相机权限才能继续');
}
/// 先查状态再决定,避免对已永久拒绝的权限再 request()(部分机型不弹框/不正常返回):
/// 已授权(含受限相册)放行;永久拒绝/受限直接引导去设置;普通拒绝才弹系统授权框。
static Future<bool> _ensure(Permission permission, String denyTip) async {
final status = await permission.status;
if (status.isGranted || status.isLimited) return true;
// 注意:Android 上 status.isPermanentlyDenied 在「从未请求过」时也会为 true
// (内部靠 shouldShowRequestRationale 判断,没问过和永久拒绝都返回 false,区分不开),
// 会误判成永久拒绝、不弹框直接去设置。所以 Android 一律先 request()
// 由系统决定弹框还是立即返回结果;iOS/macOS 的 status 可靠,永久拒绝/受限直接去设置。
// 前提:申请的权限必须已在 AndroidManifest 声明,否则 request() 会立即返回 denied 不弹框。
if ((Platform.isIOS || Platform.isMacOS) &&
(status.isPermanentlyDenied || status.isRestricted)) {
_toSettings();
return false;
}
// 普通拒绝/未询问(及 Android 全部情况):弹系统授权框,结果再统一处理
return _handleStatus(await permission.request(), denyTip: denyTip);
}
/// 处理 request() 后的结果:授权放行;永久拒绝引导去设置;普通拒绝弹 toast,
/// 下次仍会弹系统授权框,避免误报"已禁止权限"
static bool _handleStatus(PermissionStatus status,
{String denyTip = '未授权,无法继续'}) {
if (status.isGranted || status.isLimited) return true;
if (status.isPermanentlyDenied || status.isRestricted) {
_toSettings();
} else {
showToast(denyTip); //普通拒绝给个提示,避免点了没反应
}
return false;
}
/// 引导去系统设置手动开启
static void _toSettings() {
CommonAlert.show(
content: '您已禁止权限,需要去设置页面手动开启才能继续使用',
cancelText: '重试',
confirmText: '去设置',
barrierDismissible: false, //必须点按钮,点遮罩关掉会以为处理过了
).then((toSettings) {
if (toSettings) openAppSettings();
});
}
}