Home > database >  Android Kotlin: Permission Denial: reading FileProvider sending multiple files with Intent.ACTION_SE
Android Kotlin: Permission Denial: reading FileProvider sending multiple files with Intent.ACTION_SE

Time:10-02

First of all I've already read posts like this:

Attachment Issue in Intent

or this:

Permission Denial while sharing file with FileProvider

and many others to no avail, so please don't mark my answer as duplicate.

In my DrawerMenu I have an option to share my app which sends 9 screenshots through selected Intent, and even the process is working (I've tested it through Gmail) and the email with the images is sent, the following exception is always shown in logcat (which in my case is repeated 6 times):

Writing exception to parcel
java.lang.SecurityException: Permission Denial: reading com.xxxx.xxx.helpers.file.GenericFileProvider uri content://com.xxx.xxx.provider/cache/testme2.jpg from pid=5417, 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.enforceFilePermission(ContentProvider.java:674)
    at android.content.ContentProvider$Transport.openTypedAssetFile(ContentProvider.java:548)
    at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:327)
    at android.os.Binder.execTransactInternal(Binder.java:1154)
    at android.os.Binder.execTransact(Binder.java:1123)

Manifest:

<provider
    android:name=".helpers.file.GenericFileProvider"
    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>

GenericFileProvider:

import androidx.core.content.FileProvider

class GenericFileProvider : FileProvider()

Uris receiver method:

override fun onImageProcessingFinished(ipr: ImageProcessingResult) {
    val uris = ArrayList<Uri>()
    for (file in ipr.screenShotFiles) {
        val uri = FileProvider.getUriForFile(
            this,
            BuildConfig.APPLICATION_ID   ".provider", 
            file
        )
        uris.add(uri)
    }
    TMDrawerMenu.listener = this
    TMDrawerMenu.activity = WeakReference(this)
    TMDrawerMenu.shareFile(uris, "image/jpg")
}

ShareFile:

fun shareFile(uris: ArrayList<Uri>, fileType: String) {
    try {
        val share = Intent(Intent.ACTION_SEND_MULTIPLE)

        share.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        share.type = fileType
        val strSubject = "Share Subject"
        share.putExtra(Intent.EXTRA_SUBJECT, strSubject)

        share.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
        activity!!.get()!!
            .startActivity(
                Intent.createChooser(
                    share,
                    "Share Text"
                )
            )
    } catch (ex: Exception) {
        ex.logException()
    }
}

provider_paths.xml:

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

I have checked the files exists one by one, so this is not the problem.

As extra information I can say the files are saved into app's cache dir:

val outputPath = this.cacheDir.toString()

Lastly I can add I haven't tested it yet in a real device, for the moment I'm working with emulator APIs 29/30

I cannot understand the reason of the exception when the process works, but I need to find a solution because I have a similar problem in another part of the app.

The error is apparently being thrown in the next file of shareFile:

activity!!.get()!!
    .startActivity(
        Intent.createChooser(
            share,
            "Share Text"
        )
    )

Any help to get rid of this exception?

CodePudding user response:

Yes, indeed only one of all the shared files is readable by the receiving side.

I wonder why this was not reported here before.

The first thing you should add is:

if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
    intent.setClipData(ClipData.newRawUri("myfile", uris.get(0)));

The share sheet can then display some preview thumbnails.

The share sheet will complain with the same exceptions but somehow manages to read all files. Wonder wonder.

If you want the receiver (inclusive GMail) be able to read all files then change to:

                        if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) //  16 )
                        {
                            boolean makeREADpermissionValidForAllFiles = true;
                            if (makeREADpermissionValidForAllFiles)
                            {
                                ClipData clipData = ClipData.newRawUri("myfile0", uriList.get(0));
                                nr = 0;
                                while (   nr < uriList.size())
                                    clipData.addItem( new ClipData.Item(uriList.get(nr)));

                                intent.setClipData(clipData);
                            }
                            else
                                intent.setClipData(ClipData.newRawUri("myfile", uriList.get(0)));
                        }
  • Related