You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 10:40:43