使用FileProvider在Android N上打开下载的文件

alt*_*aus 11 android android-fileprovider android-7.0-nougat

由于FileProvider的更改,我必须修复我们的Android N应用程序.我基本上已经阅读了关于这个主题的所有内容,但我找不到任何解决方案.

这是我们之前的代码,它从我们的应用程序开始下载,将它们存储在Download文件夹中,并调用一个ACTION_VIEW意图作为soons,DownloadManager告诉他已完成下载:

BroadcastReceiver onComplete = new BroadcastReceiver() {
    public void onReceive(Context ctxt, Intent intent) {
        Log.d(TAG, "Download commplete");

        // Check for our download
        long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        if (mDownloadReference == referenceId) {
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(mDownloadReference);
            Cursor c = mDownloadManager.query(query);
            if (c.moveToFirst()) {
                int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
                if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
                    String localUri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                    String fileExtension = MimeTypeMap.getFileExtensionFromUrl(localUri);
                    String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);

                    if (mimeType != null) {
                        Intent openFileIntent = new Intent(Intent.ACTION_VIEW);
                        openFileIntent.setDataAndTypeAndNormalize(Uri.parse(localUri), mimeType);
                        openFileIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

                        try {
                            mAcme.startActivity(openFileIntent);
                        }
                        catch (ActivityNotFoundException e) {
                            // Ignore if no activity was found.
                        }
                    }
                }
            }
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

这适用于Android M,但由于流行而在N上打破FileUriExposedException.我现在试图通过使用FileProvider,但我不能让它工作来解决这个问题.当我尝试获取内容URI时,它正在破碎:

Failed to find configured root that contains /file:/storage/emulated/0/Download/test.pdf

localUri返回从DownloadManager该文件是:

file:///storage/emulated/0/Download/test.pdf

Environment.getExternalStorageDirectory()回报/storage/emulated/0,这是转换的代码:

File file = new File(localUri);
Log.d(TAG, localUri + " - " + Environment.getExternalStorageDirectory());
Uri contentUri = FileProvider.getUriForFile(ctxt, "my.file.provider", file);
Run Code Online (Sandbox Code Playgroud)

AndroidManifest.xml

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="my.file.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"/>
    </provider>
Run Code Online (Sandbox Code Playgroud)

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" path="." />
</paths>
Run Code Online (Sandbox Code Playgroud)

我已经尝试了在xml文件中找到的所有值.:(

alt*_*aus 8

感谢@greenaps,我能够解决这个问题.从中检索的本地URI DownlodManager以前缀为前缀file://.必须删除新的FileProvider:

if (localUri.substring(0, 7).matches("file://")) {
    localUri =  localUri.substring(7);
}
File file = new File(localUri);
Run Code Online (Sandbox Code Playgroud)

  • 请在下次您在评论中找到答案时邀请海报将其评论作为答案发布. (3认同)

Art*_*rti 6

这里改变了AndroidManifest.xml

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>
Run Code Online (Sandbox Code Playgroud)

更改文件路径

Uri contentUri;
if(Build.VERSION.SDK_INT == 24){
         contentUri = FileProvider.getUriForFile(MainActivity.this,
              getApplicationContext().getPackageName() + ".provider",
                    file);
 } else{
         contentUri = Uri.fromFile(file);
        }
Run Code Online (Sandbox Code Playgroud)