diff --git a/lib/core/utils/permission_util.dart b/lib/core/utils/permission_util.dart index e51aafb3f..83f152ee5 100644 --- a/lib/core/utils/permission_util.dart +++ b/lib/core/utils/permission_util.dart @@ -1,15 +1,8 @@ import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:app_settings/app_settings.dart'; -import 'dart:developer'; import 'logger.dart'; -// class Logger { -// static void e(String tag, String message) { -// debugPrint('[$tag] ERROR: $message'); -// } -// } - class PermissionUtil { static final PermissionUtil instance = PermissionUtil._(); PermissionUtil._(); @@ -27,18 +20,18 @@ class PermissionUtil { }) async { try { final PermissionStatus status = await permissionType.status; - log('初始权限状态 for $permissionName: $status'); + Logger.d('PermissionUtil', '初始权限状态 [$permissionName]: $status'); // 处理已授权状态(包括授予状态和临时通知权限) if (status == PermissionStatus.granted || status == PermissionStatus.provisional) { - log('$permissionName 权限已授予或临时授权。'); + Logger.i('PermissionUtil', '$permissionName 权限已授予或临时授权'); return true; } // 处理永久拒绝状态 if (status == PermissionStatus.permanentlyDenied) { - log('$permissionName 权限被永久拒绝,显示引导对话框。'); + Logger.w('PermissionUtil', '$permissionName 权限被永久拒绝,显示引导对话框'); await _showPermanentDenialDialog( context: context, permissionName: permissionName, @@ -51,7 +44,7 @@ class PermissionUtil { // 处理初始拒绝/未决定状态 if (status == PermissionStatus.denied) { - log('$permissionName 权限被拒绝或未决定,显示说明横幅并请求。'); + Logger.d('PermissionUtil', '$permissionName 权限被拒绝或未决定,显示说明横幅并请求'); _showExplanationOverlay( context: context, permissionName: permissionName, @@ -59,17 +52,17 @@ class PermissionUtil { ); final PermissionStatus newStatus = await permissionType.request(); - log('请求后 $permissionName 的新权限状态: $newStatus'); + Logger.d('PermissionUtil', '请求后 $permissionName 的新权限状态: $newStatus'); _hideExplanationOverlay(); // 处理请求后的状态 if (newStatus == PermissionStatus.granted || newStatus == PermissionStatus.provisional) { - log('$permissionName 权限在请求后被授予或临时授权。'); + Logger.i('PermissionUtil', '$permissionName 权限在请求后被授予'); return true; } else if (newStatus == PermissionStatus.permanentlyDenied) { - log('$permissionName 权限在请求后被永久拒绝,再次显示引导对话框。'); + Logger.w('PermissionUtil', '$permissionName 权限在请求后被永久拒绝'); await _showPermanentDenialDialog( context: context, permissionName: permissionName, @@ -84,21 +77,29 @@ class PermissionUtil { // 处理受限状态 if (status == PermissionStatus.restricted || status == PermissionStatus.limited) { - log('$permissionName 权限受限或受限访问: $status'); + Logger.w('PermissionUtil', '$permissionName 权限受限或受限访问: $status'); await _showRestrictedPermissionDialog(context, permissionName); return false; } // 其他未知状态处理 - log('$permissionName 处于未知状态: $status'); + Logger.e('PermissionUtil', '$permissionName 处于未知状态: $status'); return false; - } catch (e) { - Logger.e('PermissionUtil', '请求 $permissionName 权限失败: $e'); + } catch (e, stackTrace) { + Logger.e( + 'PermissionUtil', + '请求 $permissionName 权限失败: $e', + e, + stackTrace, + ); _hideExplanationOverlay(); return false; } } + /// 显示权限解释横幅(漂浮在UI顶部的说明性UI) + /// + /// 在请求权限前显示,向用户解释为什么需要这个权限 void _showExplanationOverlay({ required BuildContext context, required String permissionName, @@ -114,7 +115,7 @@ class PermissionUtil { child: Material( borderRadius: BorderRadius.circular(12), elevation: 4, - color: Colors.white, + color: Theme.of(context).colorScheme.background, child: Padding( padding: const EdgeInsets.all(16), child: Column( @@ -143,16 +144,23 @@ class PermissionUtil { Future.delayed(Duration.zero, () { if (_explanationOverlayEntry != null) { Overlay.of(context).insert(_explanationOverlayEntry!); - log('权限说明叠加层已显示。'); + Logger.i('PermissionUtil', '权限说明叠加层已显示 ($permissionName)'); } }); } + /// 隐藏权限解释横幅 void _hideExplanationOverlay() { - _explanationOverlayEntry?.remove(); - _explanationOverlayEntry = null; + if (_explanationOverlayEntry != null) { + _explanationOverlayEntry?.remove(); + _explanationOverlayEntry = null; + Logger.d('PermissionUtil', '权限说明叠加层已移除'); + } } + /// 显示永久拒绝后的设置引导对话框 + /// + /// 在权限被永久拒绝时调用,提示用户前往设置手动开启权限 Future _showPermanentDenialDialog({ required BuildContext context, required String permissionName, @@ -160,6 +168,8 @@ class PermissionUtil { required String settingsButtonText, required String cancelButtonText, }) async { + Logger.i('PermissionUtil', '显示永久拒绝对话框 ($permissionName)'); + await showDialog( context: context, barrierDismissible: false, @@ -168,11 +178,15 @@ class PermissionUtil { content: Text(permanentDenialText), actions: [ TextButton( - onPressed: () => Navigator.pop(context), + onPressed: () { + Logger.d('PermissionUtil', '用户取消设置 ($permissionName)'); + Navigator.pop(context); + }, child: Text(cancelButtonText), ), ElevatedButton( onPressed: () { + Logger.d('PermissionUtil', '用户同意前往设置 ($permissionName)'); Navigator.pop(context); AppSettings.openAppSettings(); }, @@ -183,8 +197,12 @@ class PermissionUtil { ); } + /// 显示受限权限对话框 + /// + /// 在权限受限状态(如iOS上的受限照片访问)时调用 Future _showRestrictedPermissionDialog( BuildContext context, String permissionName) async { + Logger.w('PermissionUtil', '显示受限权限对话框 ($permissionName)'); await showDialog( context: context, builder: (context) => AlertDialog( @@ -192,7 +210,10 @@ class PermissionUtil { content: const Text('此功能在当前设备上不可用或受限,请检查设备设置或系统限制'), actions: [ TextButton( - onPressed: () => Navigator.pop(context), + onPressed: () { + Logger.d('PermissionUtil', '用户确认受限权限 ($permissionName)'); + Navigator.pop(context); + }, child: const Text('确定'), ), ],