大家好!)我是Android开发的新手,现在正在尝试为Android制作文件管理器 .

我遇到了这个问题,当我尝试使用设备上安装的其他应用程序实现打开文件时,可以使用此文件 .

简要背景故事:

在Android N推出之前,我已经使用这段代码打开文件

//intent to navigate file;
            i.setDataAndType(Uri.parse("file://" + destinationPath), ext);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            // Verify that the intent will resolve to an activity
            try {
                if (i.resolveActivity(activity.getPackageManager()) != null) {
                    //start this activity
                    activity.startActivity(i);
                } else {
                    Toast.makeText(activity.getBaseContext(), R.string.browse_to_file_error_toast_1, Toast.LENGTH_LONG).show();
                }
            } catch (java.lang.Exception e) {
                Toast.makeText(activity.getBaseContext(), R.string.browse_to_file_error_toast_2, Toast.LENGTH_LONG).show();
            }

但是在Android N发布新规则后应用于Intents . 现在我们不能只将Uri附加到Intent . 如果我们的应用程序中的"targetSdkVersion"参数设置为24或更高,我们将在Android N设备上出现此错误android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()

Google完成了部分访问应用程序流程文件的访问权限,该文件由我们的应用程序启动以打开文件 . https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en

所以,我重构了代码,如下所示:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            i.setDataAndType(FileProvider.getUriForFile(activity.getBaseContext(), BuildConfig.APPLICATION_ID + ".provider", destinationPath), ext);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            // Verify that the intent will resolve to an activity
            try {
                if (i.resolveActivity(activity.getPackageManager()) != null) {
                    //start this activity
                    activity.startActivity(i);
                } else {
                    Toast.makeText(activity.getBaseContext(), R.string.browse_to_file_error_toast_1, Toast.LENGTH_LONG).show();
                }
            } catch (Exception e) {
                Toast.makeText(activity.getBaseContext(), R.string.browse_to_file_error_toast_2, Toast.LENGTH_LONG).show();
                e.printStackTrace();
            }
        }

我想,我摆脱了这个问题 . 不幸的是,我错了 . 新的代码片段仅适用于“/ storage / emulated / 0”目录中的文件(或任何路径,由Environment.getExternalStorageDirectory()方法返回) . 当我试图在外部存储器上打开文件时,例如USB闪存驱动器或设备上的SD卡(那些具有大量内置内存的设备),这段代码与FileProvider不起作用!

java.lang.IllegalArgumentException:无法在android.support的android.support.v4.content.FileProvider $ SimplePathStrategy.getUriForFile(FileProvider.java:711)中找到包含/storage/1AF0-391B/myNewFile.txt的已配置根目录 . v4.content.FileProvider.getUriForFile(FileProvider.java:400)

我发现了,为什么会发生这种错误 . 简单地说,FileProvider只能处理"/storage/emulated/0"目录中的文件 . (因此,FileProvider仅用于内部存储!)https://developer.android.com/reference/android/support/v4/content/FileProvider.html#ProviderDefinition(参见"Specifying Available Files"部分)

My question: How to deal with this bad thing? Is there any APIs, that file managers with "targetSdkVersion = 24" can use to open files on Android Nougat devices (not only on Internal storage, but also on SD cards and USB flash drives as well)?

我不想将“targetSdkVersion”参数设置为23.它“解决”了这个问题并允许我将“文件”Uri附加到Intents并且不使用任何提供者 . 但是,当Android的新版本推出时,我想让我的应用程序保持最新状态 .

谢谢你的建议!

如果我犯了错误,抱歉我的英语 .