.NET MAUI中Android 14下Permissions.RequestAsync()无法正常工作
.NET MAUI Android 14 存储权限请求无弹窗问题解决
我正在开发一个.NET MAUI应用,在Android 14中请求权限时遇到问题。使用Permissions.RequestAsync()时,权限对话框无法弹出,但在Android 12模拟器和Android 11真机上均能正常工作。奇怪的是,该权限甚至未在设备设置中显示。
现有代码
权限检查与请求代码
public static async Task<bool> HasStoragePermission() { PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.StorageWrite>(); PermissionStatus status2 = await Permissions.CheckStatusAsync<Permissions.StorageRead>(); return status == PermissionStatus.Granted && status2 == PermissionStatus.Granted; } public static async Task<bool> RequestPermissionStorage() { var status2 = await Permissions.RequestAsync<Permissions.StorageRead>(); var status = await Permissions.RequestAsync<Permissions.StorageWrite>(); return HasStoragePermission().Result; }
Android清单文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true" android:usesCleartextTraffic="true"> </application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest>
问题原因
Android 13(API 33)及以上版本彻底重构了存储权限体系,原有的READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限被废弃,替换为细分的媒体权限;Android 14进一步收紧权限规则,旧权限声明会被系统直接忽略,导致权限对话框不弹出且设置中无对应选项。
解决方案
1. 更新Android清单权限
根据业务需求替换为对应权限:
- 仅访问图片/视频/音频时,添加细分媒体权限:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
- 需要访问所有文件(含非媒体文件)时,添加特殊权限(注意该权限需引导用户手动开启):
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30" />
2. 修改权限请求代码
对应替换.NET MAUI的权限类型:
- 媒体文件权限适配代码:
public static async Task<bool> HasMediaPermission() { var imagesStatus = await Permissions.CheckStatusAsync<Permissions.Media.Images>(); var videoStatus = await Permissions.CheckStatusAsync<Permissions.Media.Video>(); var audioStatus = await Permissions.CheckStatusAsync<Permissions.Media.Audio>(); return imagesStatus == PermissionStatus.Granted && videoStatus == PermissionStatus.Granted && audioStatus == PermissionStatus.Granted; } public static async Task<bool> RequestMediaPermission() { var imagesStatus = await Permissions.RequestAsync<Permissions.Media.Images>(); var videoStatus = await Permissions.RequestAsync<Permissions.Media.Video>(); var audioStatus = await Permissions.RequestAsync<Permissions.Media.Audio>(); return await HasMediaPermission(); }
- 全文件访问权限适配代码:
public static async Task<bool> HasFullStoragePermission() { var status = await Permissions.CheckStatusAsync<Permissions.StorageManage>(); return status == PermissionStatus.Granted; } public static async Task<bool> RequestFullStoragePermission() { var status = await Permissions.RequestAsync<Permissions.StorageManage>(); // 权限被拒绝时,引导用户跳转到设置页开启 if (status == PermissionStatus.Denied && DeviceInfo.Version.Major >= 11) { AppInfo.ShowSettingsUI(); } return await HasFullStoragePermission(); }
3. 修复异步代码死锁问题
原代码中return HasStoragePermission().Result;会触发异步死锁,需改为await HasStoragePermission();。
内容的提问来源于stack exchange,提问作者Thiago Schmitz
相关产品推荐
相关产品推荐

