First of all I've already read posts like this:
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)));
}