You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
4.4 KiB
134 lines
4.4 KiB
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
import 'package:app_settings/app_settings.dart';
|
|
|
|
class PermissionUtil {
|
|
/// 检查并请求多个权限
|
|
///
|
|
/// [permissions] 要检查的权限列表,如 [Permission.microphone, Permission.location]
|
|
/// [rationaleTitle] 弹窗标题
|
|
/// [rationaleMessage] 权限用途说明内容(支持多行)
|
|
///
|
|
/// 返回是否所有权限都已被授予
|
|
static Future<bool> checkAndRequestPermissions({
|
|
required List<Permission> permissions,
|
|
required String rationaleTitle,
|
|
required List<String> rationaleMessage,
|
|
}) async {
|
|
try {
|
|
Map<Permission, PermissionStatus> statuses = {};
|
|
|
|
// 检查是否都已授权
|
|
bool allGranted = true;
|
|
for (var permission in permissions) {
|
|
final status = await permission.status;
|
|
if (!status.isGranted) {
|
|
allGranted = false;
|
|
statuses[permission] = status;
|
|
}
|
|
}
|
|
|
|
if (allGranted) return true;
|
|
|
|
// 判断是否包含永久拒绝
|
|
bool hasPermanentDenied =
|
|
statuses.values.any((status) => status.isPermanentlyDenied);
|
|
|
|
// 显示提示弹窗
|
|
_showPermissionDialog(
|
|
isPermanent: hasPermanentDenied,
|
|
title: rationaleTitle,
|
|
messages: rationaleMessage,
|
|
onConfirm: () async {
|
|
if (hasPermanentDenied) {
|
|
AppSettings.openAppSettings();
|
|
} else {
|
|
final newStatuses = await permissions.request();
|
|
final allGrantedNow =
|
|
newStatuses.values.every((status) => status.isGranted);
|
|
if (!allGrantedNow) {
|
|
print("部分权限被拒绝: $newStatuses");
|
|
}
|
|
}
|
|
},
|
|
);
|
|
|
|
return false;
|
|
} catch (e) {
|
|
print("权限检查异常: $e");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// 权限说明弹窗
|
|
static void _showPermissionDialog({
|
|
required bool isPermanent,
|
|
required String title,
|
|
required List<String> messages,
|
|
required VoidCallback onConfirm,
|
|
}) {
|
|
Get.generalDialog(
|
|
barrierDismissible: false,
|
|
barrierLabel: '权限提示',
|
|
transitionBuilder: (context, anim1, anim2, child) {
|
|
return SlideTransition(
|
|
position: Tween<Offset>(
|
|
begin: Offset(0, -1),
|
|
end: Offset(0, 0),
|
|
).animate(CurvedAnimation(parent: anim1, curve: Curves.easeOut)),
|
|
child: child,
|
|
);
|
|
},
|
|
pageBuilder: (context, anim1, anim2) {
|
|
return SafeArea(
|
|
child: Align(
|
|
alignment: Alignment.topCenter,
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(top: 80, left: 24, right: 24),
|
|
child: Material(
|
|
borderRadius: BorderRadius.circular(12),
|
|
color: Colors.white,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(title,
|
|
style: TextStyle(
|
|
fontSize: 18, fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 12),
|
|
...messages.map((msg) => Padding(
|
|
padding: const EdgeInsets.only(bottom: 8),
|
|
child: Text("• $msg"),
|
|
)),
|
|
const SizedBox(height: 20),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
TextButton(
|
|
onPressed: () => Get.back(),
|
|
child: const Text('取消'),
|
|
),
|
|
const SizedBox(width: 8),
|
|
TextButton(
|
|
onPressed: () {
|
|
Get.back();
|
|
onConfirm();
|
|
},
|
|
child: Text(isPermanent ? '前往设置' : '授权'),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|