1

i have Permission Denial while sharing a video .mp4 file with file provider and Intent.EXTRA_TEXT .

if i remove the line:

shareIntent.putExtra(Intent.EXTRA_TEXT, "#myappHashtag");

everything works. But i need both video file + extra text.

i think the problem is: caption=%23myappHashtag in the share uri but how can i fix it?

Thank you so much.

private void ShareItem(File fileToShare) {

    String package_name = "com.lucagrillo.myapp";
    Uri uri = FileProvider.getUriForFile(this, package_name + ".fileprovider", fileToShare);
    Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
    shareIntent.putExtra(Intent.EXTRA_TEXT, "#myappHashtag");
    shareIntent.setType(intentFormatType);

    startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.share_with)));

}

Exception:

Writing exception to parcel
    java.lang.SecurityException: Permission Denial: reading android.support.v4.content.FileProvider uri content://com.lucagrillo.myapp.fileprovider/images/shareFile.mp4?caption=%23myappHashtag from pid=9630, uid=10093 requires the provider be exported, or grantUriPermission()
    at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:608)
    at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:483)
    at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:474)
    at android.content.ContentProvider$Transport.openTypedAssetFile(ContentProvider.java:419)
    at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:313)
    at android.os.Binder.execTransact(Binder.java:565)

Manifest file provider:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.lucagrillo.myapp.fileprovider"
    android:grantUriPermissions="true"
    android:exported="false">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>
L.Grillo
  • 960
  • 3
  • 12
  • 26

1 Answers1

4

You missed the call to addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) on your Intent. That will work if your minSdkVersion is 21 or higher, to grant rights to that Uri to whatever app handles the ACTION_SEND request.

If your minSdkVersion is below 21, you're going to have to grant rights to all possible ACTION_SEND handlers for your Intent. On those older devices, addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) only grants permission to the Uri that you would have in the "data" facet of the Intent (e.g., new Intent(Intent.ACTION_VIEW, uri)), not Uri values in extras.

You wind up with code looking a bit like this:

  if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
    i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  }
  else {
    List<ResolveInfo> resInfoList=
      getPackageManager()
        .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY);

    for (ResolveInfo resolveInfo : resInfoList) {
      String packageName = resolveInfo.activityInfo.packageName;
      grantUriPermission(packageName, outputUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
  }

(where i is the Intent and outputUri is the Uri you put in the extra)

Also, as a reminder: ACTION_SEND implementations are not obligated to support both EXTRA_TEXT and EXTRA_STREAM.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 1
    Actually, Android as of [Jelly Bean](https://android.googlesource.com/platform/frameworks/base/+/jb-release/core/java/android/content/Intent.java#6630) migrates your stream and adds the `FLAG_GRANT_READ_URI_PERMISSION` to any `ACTION_SEND` intent automatically. – ianhanniballake Aug 29 '16 at 19:55
  • @ianhanniballake: That doesn't make much sense. `Uri` extras are not affected by `addFlags()` until Android 5.0. Is it tied to the `setClipData()` in the code that you linked to? – CommonsWare Aug 29 '16 at 20:00
  • as seen in the code linked, the `migrateExtraStreamToClipData` method converts the extras into ClipData, then adds the grant flag – ianhanniballake Aug 29 '16 at 20:15
  • @ianhanniballake: Are you saying that putting the `Uri` in the `ClipData`, then adding the flag, means that the `Uri` is readable, even if the recipient isn't using the `ClipData` itself (e.g., gets the `Uri` from `EXTRA_STREAM`)? If so, that's a good technique to know, and I can think of at least one book example of mine that I would need to update. – CommonsWare Aug 29 '16 at 20:25
  • access to the URI and how you read it out of the Intent are two independent things. Obviously this only works API 16+, but if that is your minSdkVersion, things are quite a bit easier. – ianhanniballake Aug 29 '16 at 20:27
  • @ianhanniballake: "access to the URI and how you read it out of the Intent are two independent things" -- understood. However, the idea of using `setClipData()` purely for a permission side effect hadn't crossed my mind, so I wanted to make sure that I understood the situation. Many thanks! – CommonsWare Aug 29 '16 at 20:35