Android: 如何通过Intent打开特定文件夹并在文件浏览器中显示其内容?

88

我原以为这很容易,但事实证明不幸的是它并不简单。

我的情况:

我在外部存储器上有一个名为“myFolder”的文件夹(不是SD卡,因为我使用的是Nexus 4,但这不应该是问题)。该文件夹包含一些*.csv文件。

我的目标:

我想编写一个方法来执行以下操作:显示多个应用程序(文件浏览器),供我选择(见图片)。点击后,所选的文件浏览器应启动并显示“myFolder”的内容。没有更多也没有更少。

进入图像描述

我的问题:

我应该如何做?我认为我已经接近成功,但不管我做什么 - 我确定还有一些我没有弄对的地方 - 它总是只打开外部存储器上的主文件夹。

public void openFolder()
{
File file = new File(Environment.getExternalStorageDirectory(),
    "myFolder");

Log.d("path", file.toString());

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setDataAndType(Uri.fromFile(file), "*/*");
startActivity(intent);
}

1
尝试使用这个链接,它几乎涵盖了所有的文件扩展名。 - Ameen Maheen
嗨,朋友!请查看此处 https://dev59.com/ZVUL5IYBdhLWcg3wm5J0#50073284?noredirect=1#comment87163316_50073284 并帮助解决类似问题。谢谢! - NoWar
Android 并没有标准化这个功能。只有一些文件管理器支持它-可以查看这个高度相关的Github问题 - Bip901
11个回答

80

这应该能帮助你:

Uri selectedUri = Uri.parse(Environment.getExternalStorageDirectory() + "/myFolder/");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(selectedUri, "resource/folder");

if (intent.resolveActivityInfo(getPackageManager(), 0) != null)
{
    startActivity(intent);
}
else
{
    // if you reach this place, it means there is no any file 
    // explorer app installed on your device
}
请确保您的设备上已安装任何文件浏览器应用程序。 编辑:从评论中添加了shantanu的建议。 : 如果当前解决方案无法帮助您,您也可以查看以下库https://android-arsenal.com/tag/35

12
使用这个代码可以避免在没有安装应用程序的情况下崩溃。Intent chooser = Intent.createChooser(intent, title);// 验证意图至少能够解析到一个活动 如果 (intent.resolveActivity(getPackageManager()) != null) { startActivity(chooser); } - shantanu
1
@shantanu,感谢您的推荐,我添加了一个类似的方法来检查意图是否存在。 - Ayaz Alifov
4
必须将这标记为答案... 关键是安装一个文件浏览器。ES文件浏览器对我有用,但OI文件管理器不行... - Thilina H
14
伙计,这只适用于安装了ES文件管理器的设备,因为'mime'资源/文件夹'不是标准mime类型。 - Jiawei Yang
3
这似乎只适用于ES文件浏览器。如果有其他浏览器应用程序的解决方案,请告诉我。 - Shashank Kadne
显示剩余3条评论

49

我终于把它弄好了。这种方式只显示选择器中的几个应用程序(Google Drive、Dropbox、Root Explorer和Solid Explorer)。它与这两个浏览器一起正常工作,但与Google Drive和Dropbox不兼容(我猜是因为它们不能访问外部存储器)。其他像"*/*"这样的MIME类型也是可能的。

public void openFolder(){
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()
         +  File.separator + "myFolder" + File.separator);
    intent.setDataAndType(uri, "text/csv");
    startActivity(Intent.createChooser(intent, "Open folder"));
}

11
一些应用程序,如OI文件管理器,可以使用此Intent,但Android默认的文件管理器不支持此方法。 - Ali Behzadian Nejad
2
这对我只在DropBox上起作用。你能否提供修改后的代码以打开SD卡中的文件夹? - Suresh Sharma
1
@SureshSharma 你想要使用哪个文件浏览器来打开你SD卡中的文件夹? - kaolick
这个程序在大多数手机上都能正常运行,但在三星手机上无法重定向到特定文件夹。 - PriyankaChauhan
getExternalStorageDirectory()已经被弃用,有新的解决方案吗?请使用getExternalFilesDir(null) - Noah
显示剩余2条评论

4

这里是我的回答

private fun openFolder() {
    val location = "/storage/emulated/0/Download/";
    val intent = Intent(Intent.ACTION_VIEW)
    val myDir: Uri = FileProvider.getUriForFile(context, context.applicationContext.packageName + ".provider", File(location))
    intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
        intent.setDataAndType(myDir,  DocumentsContract.Document.MIME_TYPE_DIR)
    else  intent.setDataAndType(myDir,  "*/*")

    if (intent.resolveActivityInfo(context.packageManager, 0) != null)
    {
        context.startActivity(intent)
    }
    else
    {
        // if you reach this place, it means there is no any file
        // explorer app installed on your device
        CustomToast.toastIt(context,context.getString(R.string.there_is_no_file_explorer_app_present_text))
    }
}

我使用FileProvider的原因 - android.os.FileUriExposedException: file:///storage/emulated/0/test.txt通过Intent.getData()暴露给应用程序之外

我在以下设备上测试:
设备:三星 SM-G950F(dreamltexx),操作系统API级别:28


我需要在清单文件中设置文件提供程序吗? - Slion
不知道你是怎么做到的,当按照这里所述传递文件夹时,getUriForFiles会抛出越界异常:https://dev59.com/pbHma4cB1Zd3GeqPLGgz - Slion
你可能认为它能够正常工作,因为你指定了下载文件夹。但问题在于,当指定其他文件夹时它将无法工作。 - Slion

3
Intent chooser = new Intent(Intent.ACTION_GET_CONTENT);
Uri uri = Uri.parse(Environment.getDownloadCacheDirectory().getPath().toString());
chooser.addCategory(Intent.CATEGORY_OPENABLE);
chooser.setDataAndType(uri, "*/*");
// startActivity(chooser);
try {
startActivityForResult(chooser, SELECT_FILE);
}
catch (android.content.ActivityNotFoundException ex)
{
Toast.makeText(this, "Please install a File Manager.",
Toast.LENGTH_SHORT).show();
}

在上面的代码中,如果setDataAndType为“* / *”,将打开内置文件浏览器以选择任何文件,如果我设置为“text/plain”,则会打开Dropbox。 我已安装Dropbox,Google Drive。 如果我卸载了Dropbox,则只有“* / *”可以打开文件浏览器。 这是Android 4.4.2。 我可以通过getContentResolver()。OpenInputStream(data.getData())从Dropbox下载内容,并针对Google Drive。


3

虽然这个线程有一些年头了,但是我在我的应用程序中需要这种功能,我找到了一种方法来实现它,所以如果它能帮助到任何处于我这种情况的人,我决定发布出来。

由于我们的设备组仅由三星Galaxy Tab 2组成,我只需要找到文件浏览器的包名,给出正确的路径,就可以成功打开我想要的文件浏览器。我希望我可以使用Intent.CATEGORY_APP_FILES,但它只在API 29中可用。

  Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.sec.android.app.myfiles");
  Uri uri = Uri.parse(rootPath);
  if (intent != null) {
      intent.setData(uri);
      startActivity(intent);
  }

就像我说的那样,对我们来说很容易,因为我们的客户使用相同的设备,但这可能有助于其他人找到自己情况的解决方法。


1
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, DocumentsContract.Document.MIME_TYPE_DIR);
startActivity(intent);

将打开文件应用程序的主屏幕 在这里输入图像描述

这甚至不能从通知中打开应用程序选择器。它什么也不做。 - andras
无论您发送哪个最近的 URI,它都会打开这个“无项目”。 - Dima Karaush

1
此代码适用于OI文件管理器:
        File root = new File(Environment.getExternalStorageDirectory().getPath()
+ "/myFolder/");
        Uri uri = Uri.fromFile(root);

        Intent intent = new Intent();
        intent.setAction(android.content.Intent.ACTION_VIEW);
        intent.setData(uri);
        startActivityForResult(intent, 1);

您可以在此处获取OI文件管理器:http://www.openintents.org/en/filemanager


我不得不将Uri.fromFile(...)替换为Uri.parse(...) - 正如OP的问题和被接受的答案所示。 - ban-geoengineering

0
今天,您应该使用从存储访问框架获取的内容:URI来表示文件夹,并且打开它应该很简单:
Intent i = new Intent(Intent.ACTION_VIEW, uri);
startActivity(i);

如何指定“uri”?我尝试了val filePath = Uri.parse(Environment.DIRECTORY_DOCUMENTS + "/myFolder/")但不起作用。 - Sam Chen
@SamChen 从存储访问框架中获取 是关键词。这不适用于文件:URI。 - j__m

-1
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);

intent.setType("text/csv");

intent.addCategory(Intent.CATEGORY_OPENABLE);

try {
      startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), 0);

} catch (android.content.ActivityNotFoundException ex) {
  ex.printStackTrace();
}

然后你只需要添加响应即可

public void  onActivityResult(int requestCode, int resultCode, Intent data){

switch (requestCode) {
  case 0: {
     //what you want to do
    //file = new File(uri.getPath());
  }
}
}

-2

你似乎很接近了。

我会尝试像这样设置URI:

String folderPath = Environment.getExternalStorageDirectory()+"/pathTo/folder";

Intent intent = new Intent();  
intent.setAction(Intent.ACTION_GET_CONTENT);
Uri myUri = Uri.parse(folderPath);
intent.setDataAndType(myUri , "file/*");   
startActivity(intent);

但这与您尝试过的并没有太大的区别。告诉我们它是否改变了什么?

同时确保目标文件夹存在,并在将其发送到意图(Intent)之前查看生成的Uri对象,它可能不是我们期望的内容。


1
不好意思,这个方法不起作用。和我上面的代码一样的结果。 - kaolick
在将'myUri'对象发送到意图之前,它包含了什么内容? - Guian
“URI中的内容”是什么意思?你是指像uri.toString()这样的东西吗? - kaolick
你好!请查看类似问题 https://dev59.com/ZVUL5IYBdhLWcg3wm5J0?noredirect=1#comment87161986_50072638 - NoWar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接