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

Android外部存储权限变更下图片存储方案及代码适配问题

安卓存储适配方案(兼容KitKat及以上版本)

推荐存储位置选择

  • 仅应用内部使用、不需要用户手动访问/卸载后无需保留:优先选择应用专属外部存储目录
    该目录从Android 4.4(KitKat,API 19)开始访问无需申请任何存储权限,完全适配分区存储规则,不会受Android 10+的外部存储限制影响,应用卸载时会同步删除该目录下的文件,避免产生系统垃圾。
  • 需要用户可在系统相册查看、卸载应用后仍需保留:选择公共Pictures目录下的应用专属子目录
    你可以在系统公共的Pictures文件夹下创建单独以你的应用命名的子目录存储图片,用户可以直接在系统相册、文件管理器中找到这些图片,卸载应用后文件不会被删除。这种场景需要根据系统版本适配存储权限。

代码修改方案

首先替换原Vars.DataLoc的路径获取逻辑,以下是两种方案的实现代码:

// 方案1:使用应用专属外部存储目录(推荐,无需权限)
public static string GetAppPrivateImageRootPath()
{
    // 获取应用专属外部存储的Pictures目录,可按需替换为其他目录类型
    var rootDir = Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures);
    // 拼接Images子目录路径
    string imageRootPath = Path.Combine(rootDir.AbsolutePath, "Images");
    // 目录不存在则创建
    if (!Directory.Exists(imageRootPath))
    {
        Directory.CreateDirectory(imageRootPath);
    }
    return imageRootPath;
}

// 方案2:使用公共Pictures目录下的应用子目录
public static string GetPublicImageRootPath()
{
    // 获取系统公共Pictures目录
    var rootDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures);
    // 替换为你的应用名作为子目录名,避免和其他应用文件冲突
    string imageRootPath = Path.Combine(rootDir.AbsolutePath, "你的应用名称/Images");
    if (!Directory.Exists(imageRootPath))
    {
        Directory.CreateDirectory(imageRootPath);
    }
    return imageRootPath;
}

修改后的ImageAssetManager类示例:

public static class ImageAssetManager
{
    public static Dictionary<string, Drawable> cache = new Dictionary<string, Drawable>();
    // 缓存根路径,初始化一次即可,按需替换为GetPublicImageRootPath即可切换存储方案
    private static readonly string _imageRootPath = GetAppPrivateImageRootPath();

    public static Drawable Get(string url)
    {
        string imageurl = Path.Combine(_imageRootPath, url);
        if (!cache.ContainsKey(imageurl))
        {
            Drawable drawable = Drawable.CreateFromPath(imageurl);
            cache.Add(imageurl, drawable);
        }
        return cache[imageurl];
    }

    private static string GetAppPrivateImageRootPath()
    {
        var rootDir = Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures);
        string imageRootPath = Path.Combine(rootDir.AbsolutePath, "Images");
        if (!Directory.Exists(imageRootPath))
        {
            Directory.CreateDirectory(imageRootPath);
        }
        return imageRootPath;
    }
}

兼容注意事项

  • 如果你选择公共目录方案,需要在AndroidManifest.xml中添加对应权限:
    • API < 33:添加WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE权限,运行时动态申请
    • API >= 33:如果仅访问你自己应用写入的图片,不需要申请权限;如果需要读取其他应用存入公共目录的图片,需要申请READ_MEDIA_IMAGES权限
  • 原有缓存逻辑可以按需优化:当前静态Dictionary缓存如果存储过多大图可能引发OOM,建议限制缓存上限,或者使用弱引用存储Drawable对象,内存不足时系统可自动回收。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 17:45:10