Android 11+ Java:无需打开Activity从下载目录选取PDF文件
解决方案
1. 通过MediaStore直接查询公共下载目录的PDF文件
Android 11+的Scoped Storage允许通过MediaStore查询公共目录下的文件,无需申请MANAGE_EXTERNAL_STORAGE权限,仅需常规的READ_EXTERNAL_STORAGE权限(Android 13+针对非媒体文件仍需此权限)。你可以用这种方式直接获取下载目录的PDF列表,然后自行在Fragment中构建UI展示,完全可控。
Java示例代码:
String[] projection = { MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DISPLAY_NAME, MediaStore.Files.FileColumns.DATE_MODIFIED }; // 筛选PDF文件,且位于下载目录 String selection = MediaStore.Files.FileColumns.MIME_TYPE + " = ? AND " + MediaStore.Files.FileColumns.RELATIVE_PATH + " LIKE ?"; String[] selectionArgs = {"application/pdf", "%Download%"}; // 按修改时间倒序排序 String sortOrder = MediaStore.Files.FileColumns.DATE_MODIFIED + " DESC"; Cursor cursor = requireContext().getContentResolver().query( MediaStore.Files.getContentUri("external"), projection, selection, selectionArgs, sortOrder ); if (cursor != null) { while (cursor.moveToNext()) { String fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME)); long fileId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)); // 通过ContentUri访问文件,无需直接路径 Uri contentUri = ContentUris.withAppendedId(MediaStore.Files.getContentUri("external"), fileId); // 后续可通过contentUri打开输入流读取文件内容 // InputStream inputStream = requireContext().getContentResolver().openInputStream(contentUri); } cursor.close(); }
2. 基于查询结果实现自定义Fragment内的文件选择器
拿到MediaStore查询的PDF列表后,你可以用RecyclerView在Fragment中搭建自己的文件选择UI:
- 列表项展示文件名、修改时间等信息
- 点击列表项直接获取对应的
ContentUri进行后续操作 - 还可添加搜索、排序等自定义功能,比系统选择器更贴合需求
3. 通过SAF获取下载目录的持久访问权限(适用于需深度目录操作场景)
如果需要访问下载目录下的子文件夹,或者需要持久化访问权限,可以使用Storage Access Framework(SAF)让用户一次性授权下载目录,之后就能自行遍历目录下的PDF文件:
Java示例代码:
// 打开SAF选择下载目录 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); // 默认定位到下载目录 Uri initialUri = MediaStore.Downloads.EXTERNAL_CONTENT_URI; intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialUri); // 使用ActivityResultContracts替代startActivityForResult(推荐) registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { Uri treeUri = result.getData().getData(); if (treeUri != null) { // 保存持久访问权限 requireContext().getContentResolver().takePersistableUriPermission( treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION ); // 遍历目录下的PDF文件 DocumentFile rootDir = DocumentFile.fromTreeUri(requireContext(), treeUri); if (rootDir != null) { DocumentFile[] pdfFiles = rootDir.listFiles(file -> file.getName() != null && file.getName().endsWith(".pdf") ); // 处理获取到的PDF文件列表 } } } }).launch(intent);
内容的提问来源于stack exchange,提问作者Dombi Bence
相关产品推荐
相关产品推荐

