You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms Android应用无法读取外部存储问题咨询

问题

我们开发的仅面向Android设备的Xamarin.Forms应用「myApp」,需要读写路径为

storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt

的文本文件,该路径在Windows 10开发环境中显示为

This PC\DEVICE TYPE\Internal shared storage\Android\data\com.myApp.configuration\

已在项目的AndroidManifest.xml中添加以下权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" ... >
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
</manifest>

且已在Visual Studio 2022中通过「Project > myApp.Android Properties > Android Manifest > Required permissions」确认权限已声明。

调试启动应用时,MainActivity.cs中

AndroidX.Core.App.ActivityCompat.CheckSelfPermission(this, Android.Manifest.Permission.ReadExternalStorage)

返回false,于是调用

AndroidX.Core.App.ActivityCompat.RequestPermissions(this, new string[] { Android.Manifest.Permission.ReadExternalStorage, Android.Manifest.Permission.WriteExternalStorage, Android.Manifest.Permission.ManageExternalStorage }, 0)

弹出权限申请对话框并选择「ALLOW」后,

File.Exists("/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt")

返回true,但

mystreamreader = new StreamReader("/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt");

抛出异常,提示:

"Access to the path \"/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt\" is denied."

后续检查发现

AndroidX.Core.App.ActivityCompat.CheckSelfPermission(this, Android.Manifest.Permission.ManageExternalStorage)

返回false,请问这是什么原因?

原因分析与解决方案

核心原因:MANAGE_EXTERNAL_STORAGE权限的特殊性

Android 11(API 30)及以上版本中,MANAGE_EXTERNAL_STORAGE是特殊权限,无法通过常规的RequestPermissions弹窗申请:

  • 常规的READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE可以通过弹窗授权,但MANAGE_EXTERNAL_STORAGE属于更高权限,系统会直接忽略普通弹窗请求,所以CheckSelfPermission始终返回false。

额外问题:路径归属的权限限制

你要访问的路径/storage/emulated/0/Android/data/com.myApp.configuration/是其他应用的私有目录(包名是com.myApp.configuration,而非你的应用包名):

  • Android 10(API 29)及以上版本启用了分区存储,即使有外部存储权限,也无法直接访问其他应用的私有目录,除非你的应用拥有MANAGE_EXTERNAL_STORAGE权限或者是系统应用。这就是File.Exists能检测到文件,但读取时被拒绝的根本原因。

解决步骤

  1. 正确申请MANAGE_EXTERNAL_STORAGE权限:
    不要通过RequestPermissions申请,而是引导用户跳转到系统设置页面手动开启:

    if (!Android.OS.Environment.IsExternalStorageManager)
    {
        Intent intent = new Intent(Android.Provider.Settings.ActionManageAppAllFilesAccessPermission);
        intent.AddFlags(ActivityFlags.NewTask);
        intent.SetData(Android.Net.Uri.Parse($"package:{PackageName}"));
        StartActivity(intent);
    }
    

    注意:Google Play对该权限审核严格,仅文件管理器、备份工具等特定类型应用允许上架。

  2. 优先调整存储路径(推荐):
    如果该文件是你的应用生成的,建议存储到当前应用的私有外部存储目录,无需任何特殊权限:

    // 获取当前应用的私有外部存储目录
    string appDir = Android.App.Application.Context.GetExternalFilesDir(null).AbsolutePath;
    string filePath = Path.Combine(appDir, "myAppStuff.txt");
    // 直接读写该路径,无需申请外部存储权限
    

    这个路径属于应用私有空间,不受分区存储限制,是Android官方推荐的存储方式。

内容的提问来源于stack exchange,提问作者DumbestGuyOnSaturn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 20:00:16