Android编程打开指定外部文件夹:解决ActivityNotFoundException问题
问题:打开默认文件浏览器定位指定文件夹抛出ActivityNotFoundException
我的应用会将epub文件下载至/external/downloads/{MyFolder}/路径下,通常可自动在Play Books等阅读器中打开该文件。但作为备选方案,当设备未安装阅读器时,我希望打开设备默认文件浏览器(我的设备上为“My Files”)并直接定位到{MyFolder},目前调用startActivity(intent)时抛出ActivityNotFoundException。
尝试的代码
try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); File file = new File(fileUri.getPath()); File folder = new File(file.getParent()); Uri folderUri = Uri.fromFile(folder); intent.setDataAndType(folderUri, "resource/folder"); getContext().startActivity(intent); } catch (Exception e1) { Toast.makeText(getContext(), "Ebook saving to " + fileUri.getPath(), Toast.LENGTH_LONG).show(); }
说明:该epub文件的fileUri.toString()为"content://media/external/downloads/16143"。
抛出的异常
No Activity found to handle Intent { act=android.intent.action.VIEW dat=content://com.{mydomain}.app.provider/root/external/downloads typ=resource/folder flg=0x1 }
其他尝试的代码(仍报错)
final ContentValues v = new ContentValues(); v.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + "/{MyFolder}/"); final ContentResolver r = getContext().getContentResolver(); Uri folderUri = r.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, v);
配置文件
AndroidManifest.xml
<provider android:name="androidx.core.content.FileProvider" android:authorities="com.{mydomain}.app.provider" android:exported="false" android:grantUriPermissions="true"> <!-- resource file to create --> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
file_paths.xml
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external" path="." /> <external-files-path name="external_files" path="." /> <root-path name="root" path="." /> </paths>
我还尝试将path改为./,以及移除root-path元素,但均无效果。
解决方案
1. 通用适配方案(兼容Android 10+)
核心修改点
- 替换非标准MIME类型
resource/folder为浏览器认可的vnd.android.document/directory - 使用MediaStore或FileProvider生成合规的Content Uri
- 增加Intent可处理性校验,避免异常
代码实现
try { // 确保目标文件夹存在 File targetFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "{MyFolder}"); if (!targetFolder.exists()) { targetFolder.mkdirs(); } // 生成符合Android 7+要求的Uri Uri folderUri = FileProvider.getUriForFile(getContext(), "com.{mydomain}.app.provider", targetFolder); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(folderUri, "vnd.android.document/directory"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 校验是否有浏览器能处理该Intent if (intent.resolveActivity(getContext().getPackageManager()) != null) { getContext().startActivity(intent); } else { // 降级方案:打开Downloads根目录 intent.setData(MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)); intent.setType("vnd.android.document/directory"); if (intent.resolveActivity(getContext().getPackageManager()) != null) { getContext().startActivity(intent); } else { Toast.makeText(getContext(), "未找到可用的文件浏览器", Toast.LENGTH_LONG).show(); } } } catch (Exception e) { e.printStackTrace(); Toast.makeText(getContext(), "Ebook saving to " + fileUri.getPath(), Toast.LENGTH_LONG).show(); }
2. 适配三星My Files等厂商浏览器
部分厂商浏览器支持直接通过树Uri定位,可尝试以下补充方案:
try { Uri downloadsRootUri = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY); String targetFolderPath = Environment.DIRECTORY_DOWNLOADS + "/{MyFolder}/"; // 构建目标文件夹的树Uri Uri folderUri = DocumentsContract.buildDocumentUriUsingTree(downloadsRootUri, DocumentsContract.getTreeDocumentId(downloadsRootUri) + "/" + targetFolderPath.replace("/", "%2F")); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(folderUri); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); if (intent.resolveActivity(getContext().getPackageManager()) != null) { getContext().startActivity(intent); } } catch (Exception e) { e.printStackTrace(); }
关键注意事项
- Android 10+禁止直接访问外部存储路径,必须使用Content Uri
- 跳转前必须确保目标文件夹已创建,否则会导致定位失败
- 始终通过
resolveActivity校验Intent的可处理性,避免抛出ActivityNotFoundException
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

