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

Android API31下Documents目录文件存在但应用内无法查看问题

应用无法读取Documents目录下备份文件的修复方案

问题根因定位

从实现代码和现象看,问题集中在三个方向:

  • 安卓分区存储机制下权限配置缺失,无法通过文件路径直接访问公共存储目录
  • 硬编码路径拼接存在兼容问题,传入文件选择器的路径和文件实际存储路径不匹配
  • 自定义FileChooserActivity内部存在过滤/逻辑错误,未正确加载目标目录下的json文件

分步修复方案

1. 补全存储权限与兼容配置

安卓系统从10版本开始引入分区存储,对公共目录的文件访问做了严格限制,需要先做权限适配:

  • 在AndroidManifest.xml中声明对应权限:
<!-- API 32及以下版本读外部存储权限 -->
<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />
<!-- 安卓11+如需直接通过路径访问全量存储文件时添加,注意谷歌应用商店对该权限有审核规则 -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
  • 针对安卓10版本做临时兼容,在<application>标签下添加属性:
<application
    ...
    android:requestLegacyExternalStorage="true"
    ...>
  • 所有权限需要在代码中动态申请,用户授权后再执行文件访问逻辑,不要仅在Manifest声明就直接调用。

2. 修正路径处理逻辑,增加合法性校验

现有代码硬编码/作为路径分隔符,且未做目录存在性、可读性校验,容易出现路径不匹配问题,替换为以下实现:

// 用File.separator替代硬编码斜杠,兼容不同系统的路径格式
public static final String BACKUP_PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
        + File.separator + "Kalendarz zmianowy"
        + File.separator + "Kopia zapasowa"
        + File.separator;

File backupDir = new File(BACKUP_PATH);
// 打印实际路径核对,确认和手动在文件管理器看到的目录路径完全一致
Log.d("BackupCheck", "目标目录路径:" + backupDir.getAbsolutePath());

if (!backupDir.exists()) {
    // 目录不存在时递归创建所有父级目录
    backupDir.mkdirs();
}

if (backupDir.canRead()) {
    // 确认目录有读权限再启动文件选择器
    Intent intent = new Intent(getActivity(), FileChooserActivity.class);
    intent.putExtra(FileChooserActivity.PATH, backupDir.getAbsolutePath());
    getActivity().startActivityForResult(intent, ShiftCalendarApplication.REQUEST_CODE_BACKUP);
} else {
    // 无读权限时先走权限申请流程
    applyStoragePermission();
}

3. 排查自定义文件选择器逻辑

当前启动的是应用内自定义的FileChooserActivity而非系统文件选择器,需要检查组件内部实现:

  • 确认组件没有配置文件后缀过滤规则,误将.json格式的备份文件过滤不显示
  • 确认组件加载文件列表时,是使用传入的PATH参数构造File对象调用listFiles()获取文件列表,没有写死其他根目录
  • 确认组件内部没有额外的路径拦截、权限判断逻辑,阻止了公共目录文件的加载

4. 推荐方案:替换为系统SAF文件选择器

自定义文件选择器适配多版本安卓存储机制成本很高,推荐直接使用系统自带的存储访问框架(SAF)实现文件选择,不需要申请额外存储权限,兼容性更好:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
// 仅过滤显示json格式文件
intent.setType("application/json");
// 安卓8及以上支持指定初始打开目录
Uri initialDirUri = Uri.fromFile(new File(BACKUP_PATH));
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialDirUri);
startActivityForResult(intent, ShiftCalendarApplication.REQUEST_CODE_BACKUP);

用户选择文件后,在onActivityResult回调中拿到返回的文件Uri,通过ContentResolver即可直接读取文件内容,不会出现路径不兼容、权限不足导致的文件不显示问题。


现象对照说明

两张截图的差异本质是:系统自带文件管理器拥有全存储访问权限,可以正常看到目录下的所有文件;应用内自定义选择器受权限、路径配置、自身逻辑限制,无法正确加载目录文件列表,才会显示空目录。

内容的提问来源于stack exchange,提问作者Tomasz Stępnik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:27:51