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

如何在MAUI应用中读写Android外部存储文件并获取文件列表

在MAUI中实现Android外部存储的文件读写与列表获取

一、权限配置

首先需要在Android项目中配置必要的存储权限,同时处理动态权限申请(Android 6.0+要求):

  1. 修改AndroidManifest.xml
    在Platforms/Android/AndroidManifest.xml中添加权限声明:

    <!-- Android 12及以下读写权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    <!-- Android 13+ 媒体文件权限 -->
    <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" />
    <!-- 如需访问所有外部存储(需Google Play审核) -->
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="33" />
    
  2. 动态申请权限
    MAUI提供了Permissions类简化权限申请,封装权限检查方法:

    private static async Task<bool> HasStoragePermissionsAsync()
    {
        if (DeviceInfo.Platform != DevicePlatform.Android) return true;
    
        var sdkVersion = (int)Android.OS.Build.VERSION.SdkInt;
        PermissionStatus readStatus, writeStatus;
    
        if (sdkVersion >= 33)
        {
            // Android 13+ 申请媒体读写权限
            readStatus = await Permissions.CheckStatusAsync<Permissions.MediaRead>();
            writeStatus = await Permissions.CheckStatusAsync<Permissions.MediaWrite>();
            if (readStatus != PermissionStatus.Granted)
                readStatus = await Permissions.RequestAsync<Permissions.MediaRead>();
            if (writeStatus != PermissionStatus.Granted)
                writeStatus = await Permissions.RequestAsync<Permissions.MediaWrite>();
        }
        else
        {
            // Android 6-12 申请存储读写权限
            readStatus = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
            writeStatus = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
            if (readStatus != PermissionStatus.Granted)
                readStatus = await Permissions.RequestAsync<Permissions.StorageRead>();
            if (writeStatus != PermissionStatus.Granted)
                writeStatus = await Permissions.RequestAsync<Permissions.StorageWrite>();
        }
    
        return readStatus == PermissionStatus.Granted && writeStatus == PermissionStatus.Granted;
    }
    

二、获取外部存储路径

根据需求选择对应的外部存储目录:

  1. 公共存储目录(如Downloads、Documents)
    适用于访问系统公共文件夹的场景:

    // 获取公共Downloads目录路径
    var publicDownloadsPath = Android.OS.Environment
        .GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads)
        .AbsolutePath;
    
    // 获取公共Documents目录路径
    var publicDocumentsPath = Android.OS.Environment
        .GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDocuments)
        .AbsolutePath;
    
  2. 应用专属外部存储目录
    该目录属于应用私有,卸载应用时会被清空,无需额外权限:

    var appExternalPath = Android.App.Application.Context
        .GetExternalFilesDir(null)
        .AbsolutePath;
    

三、封装抽象API实现类似Directory.GetFiles

封装跨平台兼容的方法,在Android平台完成权限校验和文件列表获取:

public static class FileHelper
{
    public static async Task<string[]> GetFilesInFolderAsync(string folderPath)
    {
        if (!await HasStoragePermissionsAsync())
            throw new UnauthorizedAccessException("未获得存储访问权限");

        if (!Directory.Exists(folderPath))
            throw new DirectoryNotFoundException("指定文件夹不存在");

        return Directory.GetFiles(folderPath);
    }

    // 权限检查方法
    private static async Task<bool> HasStoragePermissionsAsync()
    {
        if (DeviceInfo.Platform != DevicePlatform.Android) return true;

        var sdkVersion = (int)Android.OS.Build.VERSION.SdkInt;
        PermissionStatus readStatus, writeStatus;

        if (sdkVersion >= 33)
        {
            readStatus = await Permissions.CheckStatusAsync<Permissions.MediaRead>();
            writeStatus = await Permissions.CheckStatusAsync<Permissions.MediaWrite>();
            if (readStatus != PermissionStatus.Granted)
                readStatus = await Permissions.RequestAsync<Permissions.MediaRead>();
            if (writeStatus != PermissionStatus.Granted)
                writeStatus = await Permissions.RequestAsync<Permissions.MediaWrite>();
        }
        else
        {
            readStatus = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
            writeStatus = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
            if (readStatus != PermissionStatus.Granted)
                readStatus = await Permissions.RequestAsync<Permissions.StorageRead>();
            if (writeStatus != PermissionStatus.Granted)
                writeStatus = await Permissions.RequestAsync<Permissions.StorageWrite>();
        }

        return readStatus == PermissionStatus.Granted && writeStatus == PermissionStatus.Granted;
    }
}

四、使用示例

try
{
    // 替换为你需要访问的文件夹路径
    string targetFolder = "";
    if (DeviceInfo.Platform == DevicePlatform.Android)
    {
        targetFolder = Android.OS.Environment
            .GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads)
            .AbsolutePath;
    }

    var files = await FileHelper.GetFilesInFolderAsync(targetFolder);
    // 遍历文件列表做后续处理
    foreach (var file in files)
    {
        Console.WriteLine($"找到文件:{file}");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"出错:{ex.Message}");
}

五、关键注意事项

  • Scoped Storage限制:Android 10+引入了Scoped Storage,直接使用Directory类访问非应用专属的公共目录可能受限。若需访问更多目录,推荐使用MediaStore或Storage Access Framework(SAF);若必须用文件路径方式,需申请MANAGE_EXTERNAL_STORAGE权限,但该权限需通过Google Play特殊审核。
  • 应用专属存储优先:如果不需要共享文件给其他应用,优先使用应用专属外部存储,无需额外权限且不受Scoped Storage限制。
  • 跨平台兼容:若需支持多平台,建议定义抽象接口,在不同平台实现对应的文件操作逻辑,避免代码耦合。

内容的提问来源于stack exchange,提问作者Divya Prakash Jha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:20:22