如何在牛轧糖中为ACTION_VIEW使用内容URI?

时间:2018-06-22 14:26:41

标签: android uri android-7.0-nougat android-fileprovider

我有一个生成视频文件的应用程序,可以将其放置在内部存储器或SD卡中,并且需要由用户的首选视频播放器应用程序通过Intent.ACTION_VIEW打开。定位API 22时,该应用程序可以按预期工作,但尝试将其升级到27时出现问题。

该应用会根据存储位置生成不同类型的URI。对于内部存储,它使用文件URI,如下所示:

file:///storage/emulated/0/VideoRecorder/2018_06_22_12_25_50.mp4

对于放置在SD卡中的视频,它使用内容URI:

content://com.android.externalstorage.documents/tree/72D1-C625%3Avideostest%2Ftest2/document/72D1-C625%3Avideostest%2Ftest2%2F2018_06_22_12_41_27.mp4

Nougat不喜欢file:// URI,因此我使用FileProvider(下面的代码)来解决此问题,将文件URI转换为其他ACTION_VIEW可以打开的内容URI。我以为SD卡URI不需要进行任何更改,因为它已经是内容URI,但是似乎只有默认的Photos应用才能以ACTION_VIEW意图打开该URI,而用户安装的应用(如VLC Player)则不需要,失败,出现以下异常:

java.lang.SecurityException: Permission Denial: reading com.android.externalstorage.ExternalStorageProvider uri content://com.android.externalstorage.documents/tree/72D1-C625:videostest/test2/document/72D1-C625:videostest/test2/2018_06_22_12_27_45.mp4 from pid=7809, uid=10022 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()

检查了FileProvider生成的URI之后,我认为我理解了这个问题。它生成的内容URI的格式与我为SD卡视频提供的内容URI的格式完全不同:

content://io.github.androidtests.videorecorder.videosfileprovider/external_files/VideoRecorder/2018_06_22_12_25_50.mp4

我的问题是,是否还需要通过FileProvider共享SD卡视频?鉴于我只有内容URI,没有文件,而FileProvider似乎是专门设计用来将文件转换为URI的,我该怎么做?

编辑:在测试了更多的视频播放器应用程序之后,其中一些似乎可以使用内容URI,与“照片”应用程序相同。这只是某些应用尚不支持内容URI的情况吗?

代码:

Uri uri = adapter.mDataset.get(position).videoUri;

if (uri.toString().contains("file://")) {
    try {
        ParcelFileDescriptor pFD = ctx.getContentResolver().openFileDescriptor(uri, "r");
        String truePath = Utils.getFdPath(pFD);
        uri = FileProvider.getUriForFile(ctx, "io.github.androidtests.videorecorder.videosfileprovider", new File(truePath));
    } catch (FileNotFoundException e) {
        StaticMethodsAndValues.launchFabricException("RecyclerViewFragment caught FileNotFoundException when opening video.", e);
        return;
    }
}

Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setDataAndType(uri, "video/mp4");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
    ctx.startActivity(intent);
}
catch (ActivityNotFoundException e) {
    Toast.makeText(mContext.get(), mContext.get().getString(R.string.toast_no_video_player_found), Toast.LENGTH_LONG).show();
    StaticMethodsAndValues.launchFabricException("Device does not have app to handle intent action.VIEW for video/mp4.", e);
}

提供商清单定义:

<provider
    android:name=".VideosFileProvider"
    android:authorities="io.github.androidtests.videorecorder.videosfileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

提供者路径:

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

0 个答案:

没有答案