React Native安卓模块APP重装后File.listFiles无法读取旧文件如何解决
问题根因
这个问题由安卓10(API 29)及以上版本引入的分区存储机制导致,模拟器运行正常是因为多数默认禁用了分区存储限制、或运行的API版本低于29。
你已经申请的普通读写外部存储权限,在API 30及以上版本只能访问当前应用运行期新创建的公共目录文件,卸载重装后旧应用实例创建的文件会被系统判定为非当前应用所有,直接使用File.listFiles()接口会被自动过滤。
修复方案
1. 适配API 29 临时兼容方案
如果你的应用targetSdkVersion = 29,可以在AndroidManifest.xml的application节点添加属性,临时启用旧版存储模型:
<application ... android:requestLegacyExternalStorage="true">
注意:该属性仅对API 29生效,API 30及以上版本会被系统忽略。
2. 适配API 30及以上版本
API 30开始普通存储权限无法访问所有公共目录文件,需要申请全文件访问权限:
- 第一步:在
AndroidManifest.xml中添加权限声明
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
- 第二步:权限申请时跳转到系统特殊权限页让用户授权,授权状态通过
Environment.isExternalStorageManager()方法校验。
3. 替换文件读取逻辑(推荐通用方案)
直接使用FileAPI会被系统过滤旧文件,建议改用MediaStore查询公共下载目录的文件,适配所有高版本系统,示例代码如下:
@ReactMethod(isBlockingSynchronousMethod = true) public String getAllAppDownloadedFiles(String folderPath) { StringBuilder result = new StringBuilder(); Context context = getReactApplicationContext(); // 针对API 30+ 查询公共Download目录 Uri collection = MediaStore.Downloads.EXTERNAL_CONTENT_URI; String[] projection = new String[]{MediaStore.Downloads.DISPLAY_NAME, MediaStore.Downloads.DATA}; String selection = MediaStore.Downloads.DATA + " like ? "; String[] selectionArgs = new String[]{folderPath + "%"}; try (Cursor cursor = context.getContentResolver().query(collection, projection, selection, selectionArgs, null)) { int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.Downloads.DATA); while (cursor.moveToNext()) { String filePath = cursor.getString(pathIndex); File file = new File(filePath); if (file.isFile()) { if (result.length() > 0) { result.append(","); } result.append(filePath); } } } catch (Exception e) { e.printStackTrace(); } return result.toString(); }
注意事项
- 若应用需要上架Google Play,申请
MANAGE_EXTERNAL_STORAGE权限需要向谷歌提交功能用途说明,只有文件管理、备份类等符合政策要求的应用才能通过审核。 - 若业务允许,优先将文件存放在应用专属目录(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS))下,该目录的文件不需要申请存储权限即可访问,也不会出现卸载重装无法读取的问题。
内容的提问来源于stack exchange,提问作者Alen.Toma
相关产品推荐
相关产品推荐

