Android如何通过代码获取内部存储中带视频的点开头隐藏文件夹
核心原因
Android系统默认的媒体扫描服务不会索引名称以.开头的目录下的媒体文件,这类文件不会被写入MediaStore数据库,所以你通过ContentResolver查询MediaStore的接口自然拉取不到对应数据。
前提权限配置
要扫描全量内部存储的隐藏目录,你需要申请对应权限:
- Android 13及以上:先申请
READ_MEDIA_VIDEO,再引导用户开启「所有文件访问权限」(即MANAGE_EXTERNAL_STORAGE权限) - Android 11~12:直接申请
MANAGE_EXTERNAL_STORAGE权限 - Android 10及以下:申请
READ_EXTERNAL_STORAGE权限即可
可行解决方案
推荐用MediaStore查询+隐藏目录手动遍历的混合方案,兼顾效率和覆盖度:
- 先用你现有代码从MediaStore拉取所有非隐藏目录的视频文件,这部分查询速度快,不用自己遍历
- 手动递归遍历内部存储根目录下所有名称以
.开头的文件夹,匹配后缀为常见视频格式的文件,补入你的媒体列表 - 按文件父目录路径去重,即可拿到所有包含视频的文件夹(含隐藏目录)
手动遍历隐藏目录的示例代码
// 常见视频后缀集合 private static final String[] VIDEO_EXTENSIONS = {".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".rmvb", ".webm"}; // 遍历指定目录,收集所有视频文件 private void scanHiddenDirs(File dir, ArrayList<MediaFiles> mediaFilesArrayList, HashSet<String> allFolderList) { // 跳过无访问权限的系统目录 if (dir == null || !dir.exists() || !dir.canRead() || dir.getAbsolutePath().startsWith("/sdcard/Android/")) { return; } File[] files = dir.listFiles(); if (files == null) return; for (File file : files) { if (file.isDirectory()) { // 递归遍历所有子目录 scanHiddenDirs(file, mediaFilesArrayList, allFolderList); } else { // 判断是不是视频文件 String fileName = file.getName(); for (String ext : VIDEO_EXTENSIONS) { if (fileName.toLowerCase().endsWith(ext)) { // 构造MediaFiles对象 String path = file.getAbsolutePath(); String parentPath = path.substring(0, path.lastIndexOf("/")); // 去重添加文件夹 SharedPreferences sharedPreferences = getSharedPreferences(HIDDEN_VIDEOS_PREFS, MODE_PRIVATE); if (!allFolderList.contains(parentPath) && sharedPreferences.getString(HIDDEN_VIDEO_KEY + parentPath, "-").equals("-")) { allFolderList.add(parentPath); } // 补入媒体列表 MediaFiles mediaFile = new MediaFiles( String.valueOf(file.hashCode()), // 自定义唯一id fileName.substring(0, fileName.lastIndexOf(".")), // 视频标题 String.valueOf(getVideoDuration(path)), // 可用MediaMetadataRetriever获取时长 String.valueOf(file.length()), // 文件大小 String.valueOf(file.lastModified()/1000), // 转换为秒级时间戳 path, fileName, false ); mediaFilesArrayList.add(mediaFile); break; } } } } }
调用方法
在你原有fetchMedia方法执行完毕后,调用遍历方法补全隐藏目录的内容:
// 原有MediaStore查询逻辑执行完后添加此行,传入内部存储根目录 scanHiddenDirs(Environment.getExternalStorageDirectory(), mediaFilesArrayList, allFolderList);
注意事项
- 拿视频时长的
getVideoDuration方法可以用MediaMetadataRetriever自行封装,大文件较多的话建议放在子线程执行避免卡顿 - 必须等用户授予所有文件访问权限后再执行遍历操作,否则会出现无权限读取的问题
- 可以按需新增过滤规则,排除不需要扫描的目录提升执行效率
内容的提问来源于stack exchange,提问作者Ali Zahid
相关产品推荐
相关产品推荐

