如何使用MediaStore列出指定目录下的所有文件?
用MediaStore筛选指定文件夹下的文件
要实现指定文件夹的文件筛选,核心是在查询的selection条件中添加文件夹路径匹配规则,同时需要兼容Android 10(API 29)及以上版本的字段变化:
关键差异说明
- Android 10及以上:
MediaStore.Files.FileColumns.DATA字段被废弃,需使用RELATIVE_PATH字段匹配相对路径(相对于外部存储根目录,比如Download/MyFolder/) - Android 10以下:依然使用
DATA字段匹配文件的绝对路径
修改后的完整代码
假设我们要筛选的目标文件夹是:
- Android 10以下:
/storage/emulated/0/Download/MyTargetFolder - Android 10及以上:相对路径
Download/MyTargetFolder/(注意末尾必须带斜杠)
Uri collection; final String sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + " DESC"; String selection; String[] selectionArgs; // 目标文件夹配置 final String targetFolderAbsPath = Environment.getExternalStorageDirectory().getPath() + "/Download/MyTargetFolder/"; final String targetFolderRelativePath = "Download/MyTargetFolder/"; // MIME类型筛选条件 final String mimeTypePdf = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf"); final String mimeTypeJpg = MimeTypeMap.getSingleton().getMimeTypeFromExtension("jpg"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Android 10+ 使用RELATIVE_PATH筛选 selection = "(" + MediaStore.Files.FileColumns.MIME_TYPE + " = ? OR " + MediaStore.Files.FileColumns.MIME_TYPE + " = ?)" + " AND " + MediaStore.Files.FileColumns.RELATIVE_PATH + " = ?"; selectionArgs = new String[]{mimeTypePdf, mimeTypeJpg, targetFolderRelativePath}; collection = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL); } else { // Android 10以下 使用DATA字段匹配绝对路径前缀 selection = "(" + MediaStore.Files.FileColumns.MIME_TYPE + " = ? OR " + MediaStore.Files.FileColumns.MIME_TYPE + " = ?)" + " AND " + MediaStore.Files.FileColumns.DATA + " LIKE ?"; selectionArgs = new String[]{mimeTypePdf, mimeTypeJpg, targetFolderAbsPath + "%"}; collection = MediaStore.Files.getContentUri("external"); } try (Cursor cursor = getContext().getContentResolver().query(collection, null, selection, selectionArgs, sortOrder)) { if (cursor != null && cursor.getCount() > 0) { while (cursor.moveToNext()) { // 注意:Android 10+ 不要使用DATA字段获取路径,改用CONTENT_URI构建 String filePath; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID)); Uri contentUri = ContentUris.withAppendedId(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), id); filePath = contentUri.toString(); } else { filePath = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)); } String fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DISPLAY_NAME)); long date = cursor.getLong(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATE_MODIFIED)); ModalClass mediaFiles = new ModalClass(); mediaFiles.setFileName(fileName); mediaFiles.setPath(filePath); mediaFiles.setDate(date); fileList.add(mediaFiles); } } }
重要注意事项
- RELATIVE_PATH的格式:Android 10+中,
RELATIVE_PATH的值末尾带有斜杠,所以目标路径必须保持一致(比如Download/MyFolder/而非Download/MyFolder) - Android 10+路径获取:不要再使用
DATA字段,通过_ID构建ContentUri作为文件路径,避免权限问题 - 权限要求:确保已申请
READ_EXTERNAL_STORAGE权限(Android 13及以上针对特定类型文件可能需要更细分的权限,比如READ_MEDIA_IMAGES、READ_MEDIA_DOCUMENTS)
内容的提问来源于stack exchange,提问作者Aisha
相关产品推荐
相关产品推荐

