Android如何从指定文件夹读取PDF并在RecyclerView中展示
从特定文件夹读取PDF文件的代码修改方案
要实现从特定文件夹读取PDF,不能直接修改MediaStore的Collection Uri,而是要通过添加路径过滤条件来筛选目标文件夹下的文件。以下是针对你的代码的修改版本,兼容Android Q(API 30)及以上、以下版本:
1. 定义目标文件夹常量
首先明确你要读取的目标文件夹(示例为外部存储根目录下的Abbas_1122文件夹,如果是子文件夹,比如Downloads下的子文件夹,可写成"Downloads/Abbas_1122/"):
private static final String TARGET_FOLDER = "Abbas_1122/"; // 末尾加斜杠,匹配RELATIVE_PATH的格式要求
2. 修改ReadSDcard函数
核心修改是添加路径过滤条件,结合MIME类型筛选PDF文件:
/** * 从特定文件夹读取PDF文件 */ private List<PdfModel> ReadSDcard() { List<PdfModel> myList = new ArrayList<>(); String[] projection = { MediaStore.Files.FileColumns.DATA, MediaStore.Files.FileColumns.DATE_ADDED, MediaStore.Files.FileColumns.DISPLAY_NAME, MediaStore.Files.FileColumns.MIME_TYPE, MediaStore.Files.FileColumns.DATE_MODIFIED, MediaStore.Files.FileColumns.RELATIVE_PATH // 新增字段,用于API30+的路径过滤 }; String pdfMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf"); StringBuilder selectionBuilder = new StringBuilder(); List<String> selectionArgsList = new ArrayList<>(); // 基础条件:筛选PDF文件 selectionBuilder.append(MediaStore.Files.FileColumns.MIME_TYPE).append(" = ?"); selectionArgsList.add(pdfMimeType); // 添加特定文件夹过滤条件,分API版本处理 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // API30+:使用RELATIVE_PATH字段匹配目标文件夹 selectionBuilder.append(" AND ").append(MediaStore.Files.FileColumns.RELATIVE_PATH).append(" LIKE ?"); selectionArgsList.add("%" + TARGET_FOLDER + "%"); Uri collection = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY); myList.addAll(getListOfPdfFiles(collection, projection, selectionBuilder.toString(), selectionArgsList.toArray(new String[0]))); } else { // API30以下:使用DATA字段匹配目标文件夹绝对路径 String targetFolderPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + TARGET_FOLDER; selectionBuilder.append(" AND ").append(MediaStore.Files.FileColumns.DATA).append(" LIKE ?"); selectionArgsList.add("%" + targetFolderPath + "%"); Uri collection = MediaStore.Files.getContentUri("external"); myList.addAll(getListOfPdfFiles(collection, projection, selectionBuilder.toString(), selectionArgsList.toArray(new String[0]))); } return myList; }
3. 适配getListOfPdfFiles函数
针对API30+的路径获取逻辑做兼容(Android Q之后DATA字段可能不再返回真实路径):
private List<PdfModel> getListOfPdfFiles(Uri collection, String[] projection, String selection, String[] selectArgs) { List<PdfModel> pdfList = new ArrayList<>(); try { Cursor cursor = getApplicationContext().getContentResolver().query(collection, projection, selection, selectArgs, null); if (cursor != null && cursor.moveToFirst()) { int dataColumnIndex = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA); int relativePathIndex = cursor.getColumnIndex(MediaStore.Files.FileColumns.RELATIVE_PATH); int displayNameIndex = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME); do { try { String filePath; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // API30+:优先用DATA字段,为空则用RELATIVE_PATH拼接路径 String dataPath = cursor.getString(dataColumnIndex); if (dataPath != null && !dataPath.isEmpty()) { filePath = dataPath; } else { String relativePath = cursor.getString(relativePathIndex); filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + relativePath + cursor.getString(displayNameIndex); } } else { // API30以下:直接使用DATA字段的路径 filePath = cursor.getString(dataColumnIndex); } File file = new File(filePath); String fileName = file.getName(); PdfModel pdfModel = new PdfModel(fileName, "129", 0, "pdf", filePath); pdfList.add(pdfModel); } catch (Exception e) { e.printStackTrace(); } } while (cursor.moveToNext()); cursor.close(); } } catch (Exception e) { e.printStackTrace(); } return pdfList; }
关键说明
- Uri的正确用法:MediaStore的Collection Uri不能直接指定文件夹路径,必须通过
selection条件过滤,你之前修改collection Uri的方式是错误的 - API版本兼容:Android Q之后
DATA字段可能被限制,因此用RELATIVE_PATH匹配目标文件夹;Q之前可直接用DATA字段判断路径 - 路径匹配规则:使用
LIKE和通配符%会匹配目标文件夹及子文件夹下的PDF,如果不需要子文件夹,可去掉前后的%,写成TARGET_FOLDER
内容的提问来源于stack exchange,提问作者Muhammad Abbas
相关产品推荐
相关产品推荐

