代码之家  ›  专栏  ›  技术社区  ›  NoWar

FileUriExposedException在Android中[重复]

  •  12
  • NoWar  · 技术社区  · 7 年前

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

    我使用以下代码。

    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 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>
    

    显示

      <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/file\u路径

    <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>
    

    错误

    致命异常:主进程:android。应用程序。bnb。公司我的照片,PID: 22482 安卓操作系统。FileUriExposedException:file:///storage/emulated/0/Pictures/MyPhotos暴露在应用程序之外 通过意图。getData()

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

    更新#1

    使用此弧 https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en 我替换了

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

    具有

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

    错误消失了。

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

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

    3 回复  |  直到 7 年前
        1
  •  10
  •   Sagar    7 年前

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

    是(&不可以。并不能百分之百保证它能在所有设备上工作。

    编辑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 file explorer应用程序时,此方法才有效。

    如果您选择使用,则必须检查是否有任何意图可以通过使用:

    PackageManager PackageManager=getActivity()。getPackageManager();

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

    3、使用类型 */*

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

    如果用户从意图选择器中选择File Manager应用程序并将其标记为要处理的默认应用程序,则此方法有效 */* . 然而,它也有一些缺点(感谢@Commonware带来了一些缺点):

    • 此类型将加载设备上的所有应用程序,并允许用户选择其中一个来完成操作。
    • 如果没有文件浏览器,并且用户选择其他应用加载您的意图,那么其他应用将崩溃或只是显示黑屏。E、 g.您使用Gallery或其他应用程序启动它,而不是使用文件浏览器,那么Gallery应用程序将崩溃或显示黑屏。
    • 即使存在文件资源管理器,但用户决定使用其他应用程序,其他应用程序也可能崩溃

    4、使用类型 text/csv

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

    这将限制向用户显示的应用程序的数量,但在 */* 已使用。可处理的应用程序 csv 将显示,如果用户选择它,则应用程序将崩溃。

    有一些特定于设备的实现可用 here 如所述 @程序员学会 这需要确定默认文件管理器的意图以及它对额外文件的需求。

    结论:

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

        2
  •  4
  •   ColdFire    7 年前

    我使用以下代码从存储器中打开图像:

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());
    
    File path = new File(Environment.getExternalStorageDirectory() + "/" + "ParentDirectory" + "/" + "ChildDirectory");
    
    File filepath = new File(path + "/" + yourImageName.png);
    
    Uri uri = Uri.fromFile(filepath);
    
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(uri, "image/jpeg");
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
    

    编辑的答案:

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());
    
    File path = new File(Environment.getExternalStorageDirectory() + "/" + "ParentDirectory" + "/" + "ChildDirectory");
    
    Uri uri = Uri.fromFile(path);
    
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(uri, "image/jpeg");
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
    
        3
  •  0
  •   NoWar    7 年前

    我在这里找到了解决方案 can we open download folder via. intent?

    这段代码在我的三星J7中非常有效,可以使用三星默认应用程序从内存中打开图片文件夹(和其他文件夹) 我的文件 .

    File path = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_PICTURES);
    Uri uri = Uri.fromFile(path);
    Intent intent = getPackageManager().getLaunchIntentForPackage("com.sec.android.app.myfiles");
    intent.setAction("samsung.myfiles.intent.action.LAUNCH_MY_FILES");
                        intent.putExtra("samsung.myfiles.intent.extra.START_PATH", path.getAbsolutePath());
    startActivity(intent);
    

    看来我们必须反编译 文件管理器 了解如何正确调用:(而且这项工作太多了。嗯……我假设有一些通用的解决方案可以做到这一点。