Android 中的 FileUriExposedException [重复]

2023-12-30

我需要打开内部存储中包含图像的文件夹。

我使用以下代码。

Java

 File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),  "MyPhotos");
Intent intent = new Intent(Intent.ACTION_VIEW);
String path =folder.getPath();
Uri myImagesdir = Uri.parse("file://" + path );
intent.setDataAndType(myImagesdir,"*/*");   
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);

PATHS

 <paths xmlns:android="http://schemas.android.com/apk/res/android">
     <external-path name="images" path="Pictures" />
     <external-path name="external_files" path="."/>
     <external-path name="files_root" path="Android/data/${applicationId}"/> </paths>

Manifest

  <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.android.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

xml/文件路径

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="images" path="Pictures" />
    <external-path name="external_files" path="."/>
    <external-path name="files_root" path="Android/data/${applicationId}"/>
</paths>

ERROR

致命异常:主进程:android.apps.bnb.company.myphotos,PID: 22482 android.os.FileUriExposeException:file:///storage/emulated/0/Pictures/MyPhotos 暴露在应用程序之外 通过Intent.getData()

还有其他方法可以打开内部存储中的文件夹吗?谢谢!

更新#1

使用这篇文章https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en我更换了

Uri myImagesdir = Uri.parse("file://" + path );

with

 Uri myImagesdir = Uri.parse("content://" + path );

错误消失了。

无论如何,我必须选择始终应用程序来打开此文件夹。

是否可以默认使用“我的文件”应用程序打开某些文件夹?


是否可以默认使用“我的文件”应用程序打开某些文件夹?

是和否。不能 100% 保证它适用于所有设备。

Edit 1:

以下是可以完成的方法之一。我已经在几个模拟器(运行 Android N 和 Android O)上进行了测试并加载默认文件资源管理器:

MainActivity.java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri dirUri = FileProvider.getUriForFile(this,getApplicationContext().getPackageName() + ".com.example.myapplication",Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS));
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        //intent.setDataAndtType(); I will change this value in the alternatives below
    }

AndroidManifest.xml

<provider
        android:name=".GenericFileProvider"
        android:authorities="${applicationId}.com.example.myapplication"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
</provider>

GenericFileProvider.java

public class GenericFileProvider extends FileProvider {
}

file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

上述方法不适用于三星这样的大公司

备择方案

1、使用类型DocumentsContract.Document.MIME_TYPE_DIR

intent.setDataAndType(dirUri,DocumentsContract.Document.MIME_TYPE_DIR);

此方法适用于多个模拟器和有限的设备集。它不适用于三星或华为等大公司。

2、使用类型resource/folder

intent.setDataAndType(dirUri,"resource/folder");

仅当用户安装了 ES 文件浏览器应用程序时,此方法才有效。

如果您选择使用 ,那么您必须使用以下方法检查是否有任何意图可以处理它:

PackageManager packageManager = getActivity().getPackageManager();

if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
   // either display error or take necessary action
}

3、使用类型*/*

intent.setDataAndType(dirUri,"*/*");

如果用户从意图选择器中选择文件管理器应用程序并将其标记为要处理的默认应用程序,则此方法有效*/*。然而它有一些缺点(感谢@CommonsWare 提出了其中一些缺点):

  • 此类型将加载设备上的所有应用程序,并允许用户选择其中一个来完成操作。
  • 如果没有文件资源管理器并且用户选择其他应用程序来加载您的意图,则其他应用程序将崩溃或仅显示黑屏。例如。您使用图库或其他应用程序而不是文件资源管理器来启动它,然后图库应用程序将崩溃或显示黑屏。
  • 即使有文件资源管理器但用户决定使用其他应用程序,其他应用程序也可能崩溃

4、使用类型text/csv

intent.setDataAndType(uri, "text/csv")

这将限制向用户显示的应用程序数量,但在以下情况下也有相同的限制:*/*使用已应用。可以处理的应用程序csv将显示,如果用户选择它,则应用程序将崩溃。

有一些设备特定的实现可用here https://stackoverflow.com/questions/21621077/can-we-open-download-folder-via-intent/21622373正如所提到的@程序员学院这需要识别默认文件管理器的意图和它的额外需求。

结论:

没有可用的标准类型来实现它,因为目前文件管理器没有遵循的标准来支持特定类型。未来谷歌可能会想出一些办法。最好的选择是实现您自己的文件管理器,就像 Dropbox 或 Google Drive 一样。有几个可用的库提供此功能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 中的 FileUriExposedException [重复] 的相关文章

随机推荐