Xamarin Android应用在Android 13(API 33)中无法读取文件求助
核心认知纠正
你代码中使用的System.Environment.SpecialFolder.Personal对应Android应用的私有内部存储目录(路径类似/data/user/0/com.player/files/),这类目录的读写权限是系统默认授予应用的,完全不需要申请READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE权限。Android从始至终都允许应用直接访问自己的私有沙盒目录,和系统版本无关。
具体解决方案
1. 移除Manifest中不必要的权限
直接删除AndroidManifest.xml中以下权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这些权限仅用于访问公共外部存储(比如Downloads、Pictures等公共目录),和你的私有目录访问逻辑无关。保留它们反而可能因为权限申请逻辑混乱,触发不必要的权限检查错误。
2. 排查文件读取代码逻辑
确认读取文件的代码是否存在异常处理缺失,或者错误的权限前置检查:
try { string passFilePath = Pass(); if (File.Exists(passFilePath)) { string fileContent = File.ReadAllText(passFilePath); // 业务逻辑处理 } else { // 文件不存在的处理逻辑 } } catch (Exception ex) { // 打印具体异常信息,定位问题根源 Console.WriteLine($"读取文件失败:{ex.Message}\n{ex.StackTrace}"); }
如果异常仍提示权限被拒,但路径是私有目录,大概率是你在读取操作前错误地加入了「检查外部存储权限」的逻辑——Android 13中READ_EXTERNAL_STORAGE权限的授予逻辑和旧版本不同,未授予该权限时,代码错误地终止了私有目录的读取操作。
3. 验证路径正确性
打印实际路径确认是否指向私有目录:
Console.WriteLine("Pass文件路径:" + Pass());
Android 13下私有目录路径格式应为/data/user/0/com.player/files/pass.licns,若路径正确,应用必然拥有读写权限。
4. 无关属性处理
Manifest中的android:requestLegacyExternalStorage="false"仅针对Android 10的分区存储适配,和Android 13的私有目录访问无关,可保留或直接移除。
额外说明
如果你的应用还需要访问公共外部存储的媒体文件,Android 13需要替换权限:
- 图片用
READ_MEDIA_IMAGES - 音频用
READ_MEDIA_AUDIO - 视频用
READ_MEDIA_VIDEO
非媒体文件则需申请MANAGE_EXTERNAL_STORAGE权限(但该权限需Google Play特殊审核,仅适用于文件管理器类应用)。
内容的提问来源于stack exchange,提问作者DedSec

