7

There have been several posts about this that I have reviewed and I've tried a half a dozen of the proposed solutions. I have something almost identical to this working without throwing an exception in another app I wrote but I'm just not able to get this not to throw an exception, although the file does get transferred! The permission is being set and the file does transmit just fine, but an exception still gets thrown although it does not crash the app.

What I have is this:

fun shareVideo(videoFile: File, context: Context) {
  if(videoFile.exists()) {
    Timber.i("Video file exists and the length in bytes is: ${videoFile.length()}")
  } else {
    Timber.w("Video file does not exist. Exiting.")
    return
  }

  val uris = arrayListOf<Uri>()
  val uri = FileProvider.getUriForFile(context.applicationContext, context.packageName + ".provider", videoFile)

  Timber.i("Uri: $uri + path: ${uri.path}")

  uris.add(uri)

  val intent = Intent()
  intent.action = Intent.ACTION_SEND_MULTIPLE
  intent.putExtra(Intent.EXTRA_SUBJECT, "Shared files")
  intent.type = "video/mp4"
  intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
  intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
  intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

  Timber.i("Intent: $intent")

  try{
      ContextCompat.startActivity(context, Intent.createChooser(intent, "Shared Videos"), null)
  } catch (e: Exception) {
    Timber.e("Exception starting activity. \nException was ${e.message}\n Stack trace to follow:\n ${e.stackTrace}")
  }
}

The stack trace looks like this:

2021-03-07 14:21:59.570 6039-6207/com.company.app E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri content://com.company.app.provider/external_files/1615148514218.mp4 from pid=32136, uid=1000 requires the provider be exported, or grantUriPermission()
    at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:820)
    at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:684)
    at android.content.ContentProvider$Transport.query(ContentProvider.java:239)
    at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:106)
    at android.os.Binder.execTransactInternal(Binder.java:1154)
    at android.os.Binder.execTransact(Binder.java:1123)

The Timber log output looks like this:

2021-03-07 14:33:32.713 7396-7396/com.company.app I/StorageUtilsKt: Video file exists and the length in bytes is: 7511455
2021-03-07 14:33:32.719 7396-7396/com.company.app I/StorageUtilsKt: Uri: content://com.company.app.provider/external_files/1615149206171.mp4 + path: /external_files/1615149206171.mp4
2021-03-07 14:33:37.337 7396-7396/com.company.app I/StorageUtilsKt: Intent: Intent { act=android.intent.action.SEND_MULTIPLE typ=video/mp4 flg=0x10000001 (has extras) }
2021-03-07 14:33:38.604 7396-7589/com.company.app E/DatabaseUtils: Writing exception to parcel

So the file is there, and I see it in the attachment that it does add it and I do get it via email/etc. and can view it, but the exception is thrown in the logs.

My provider_paths.xml file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<paths>
  <cache-path          name="cache"          path="/"/>
  <external-cache-path name="external_cache" path="." />
  <external-path       name="external"       path="." />
  <external-files-path name="external_files" path="." />
  <files-path          name="app_videos"     path="." />
</paths>

And my manifest has this in it:

        <provider
          android:name="androidx.core.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>

Everything looks exactly like the app I have that works yet this one throws that exception.

Can anyone see what's wrong with what I am doing?

user443654
  • 821
  • 1
  • 7
  • 21
  • 3
    Try temporarily removing `Intent.createChooser()` and use `intent` directly. If that works, perhaps [switch to `setClipData()` or `ShareCompat.IntentBuilder`](https://commonsware.com/blog/2021/01/07/action_send-share-sheet-clipdata.html). – CommonsWare Mar 07 '21 at 21:54
  • 1
    The full path is in the logs above but here it is: Uri: content://com.company.app.provider/external_files/1615149206171.mp4. Again, this does work and I can see the video on the other end in email/etc. but I don't like that it throws this exception when I haven't seen that before. – user443654 Mar 08 '21 at 03:06
  • I'm seeing the same behavior as you. Did you ever fix it or see any negative consequences of not fixing it? – mtrewartha Feb 16 '22 at 17:52

2 Answers2

4

Use ShareCompat.IntentBuilder. It is doing all the right things for you. For the underlying issue, see https://issuetracker.google.com/issues/173137936

fun shareVideo(videoFile: File, context: Context) {
    if (videoFile.exists()) {
        Timber.i("Video file exists and the length in bytes is: ${videoFile.length()}")
    } else {
        Timber.w("Video file does not exist. Exiting.")
        return
    }

    val uri = FileProvider.getUriForFile(context, context.packageName + ".provider", videoFile)

    ShareCompat.IntentBuilder(context)
        .setType("video/mp4")
        .setSubject("Shared files")
        .addStream(uri)
        .setChooserTitle("Shared Videos")
        .startChooser()
}
cketti
  • 1,277
  • 11
  • 15
2

Check this one here https://stackoverflow.com/a/59439316

you need to grant permissions to each available app which is available for this intent.

  • 3
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 08 '21 at 15:48
  • Obrigado André deu certo! – Will V Feb 25 '22 at 13:42