1

I've ported my application to android API 24. My application downloads file to a folder called test in external storage, and after download it will open the download file. As an example consider file with address /storage/emulated/0/test/video.mp4. Its address is created usign this syntax:

File file = new File(Environment.getExternalStorageDirectory()+ "/test/" + fileName);

To create its URI to load it using an intent, I used instructions in this answer. Here is the provider tag in my manifest (which is nested inside application tag):

<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/provider_paths"/>
</provider>

And here is the provide in /res/xml/provider_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="test" />
</paths>

After all, when I use this syntax to create the URI:

uri = FileProvider.getUriForFile(mCurrentActivity, mCurrentActivity.getPackageName() + ".provider", file);

and it will result uri string content://my.package.name.provider/external_files/video.mp4.

However trying to open URI using intents, file is not opened in application related to that mime-type (I've checked the file and it is downloaded and can be played/opened in viewers with no problem).

Here is the code to open the URI which if fully functional in versions less than 24 using Uri.FromFile:

intent.setDataAndType(uri, mimeType);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(
        mCurrentActivity, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

Based on comments I updated the code to this but it does not change the situation:

intent.setDataAndType(uri, mimeType)
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
PendingIntent contentIntent = PendingIntent.getActivity(
        mCurrentActivity, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Community
  • 1
  • 1
VSB
  • 9,825
  • 16
  • 72
  • 145
  • 1
    I recommend that you edit your question and explain, in greater detail, what "will point to wrong address and does not open the file" means. Note that you do not seem to add `FLAG_GRANT_READ_URI_PERMISSION` to the `Intent`, and without that, nobody has the rights to work with the content identified by a `Uri` pointing to your `FileProvider.` – CommonsWare Feb 16 '17 at 00:02
  • @CommonsWare Thanks for your comment. I've edited the question and updated the code but situation is the same. – VSB Feb 16 '17 at 00:22
  • "file is not opened in application related to that mime-type" -- please explain, **in detail**, what you mean by this. – CommonsWare Feb 16 '17 at 00:27
  • 1
    @CommonsWare For older versions of android, when intent fires with uri created by `Uri.FromFile`, intent chooser window shows up and when I select player, it opens and start to play file (for video files as an example). But this time, when I use `FileProvider.getUriForFile` to create URI, when intent fires, intent chooser shows up, when I select player it opens but prompts `Can't Play this Video`. As i described nothing is wrong with video or download process. – VSB Feb 16 '17 at 00:35
  • 1
    See if that player app is logging anything useful to LogCat. I have not attempted to play a video from `FileProvider`. AFAIK, it should work. – CommonsWare Feb 16 '17 at 00:40
  • @CommonsWare I found some clues in logcat: `/ActivityManager(1531): Permission Denial: opening provider android.support.v4.content.FileProvider from (null) (pid=1279, uid=1013) that is not exported from uid 10076 openContentUri(content://my.package.name/external_files/video.mp4) caught exception -1 Couldn't open fd for content://my.package.name/external_files/video.mp4` – VSB Feb 16 '17 at 00:53
  • Those would be the errors if you do not have `FLAG_GRANT_READ_URI_PERMISSION` on the `Intent`. – CommonsWare Feb 16 '17 at 12:53
  • @CommonsWare It seems that I should add permission manually for each package which can resolve my intent. – VSB Feb 16 '17 at 14:43

1 Answers1

1

As described in this answer and this one I should grant permission manually to each package which can handle my (implicit) intent using this snippet:

intent.setDataAndType(uri, mimeType)
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//add this: allow permissions to all packages which can handle intent
List<ResolveInfo> resInfoList = mCurrentActivity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    mCurrentActivity.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
Community
  • 1
  • 1
VSB
  • 9,825
  • 16
  • 72
  • 145
  • That should not be necessary. You might consider combining the two `addFlags()` calls, and you might try testing not adding `FLAG_ACTIVITY_NEW_TASK`. – CommonsWare Feb 16 '17 at 15:03