If we look at the be behaviour changes in android-7 Nougat. You will find file:// URI sharing outside the app is prohibited and may result in FileUriExposedException
.
This is when FileProvider
subclass of content provider comes to the rescue, which has a method getUriForFile()
which returns URI that can be shared outside the app. You follow the standard steps mentioned in android docs and implement the in your app. So far everything looks fine.
And then when your sharing the URI, if you have used ShareCompat
like me, you add URI in only one of the two methods addStream()
or setStream()
with Intent.FLAG_GRANT_READ_URI_PERMISSION
flag applied, and then call createChooserIntent()
and start activity which brings up the standard Android activity chooser. However even though you have done everything right, you see a strange log in the logcat.
java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri ..
At this point you would be tempted to export the file-provider at this point, or run a for loop granting all packages the permission using context.grantUriPermission()
as below code snippet, which again not a great solution.
After lot of RnD i found the answer to the above problem in hidden documentation of FLAG_GRANT_READ_URI_PERMISSION, which states the permission grants read operations on the URI in the Intent’s data and any URIs specified in its ClipData.
If you have observed ShareCompat
does not expose a direct API to set the URI
in data or ClipData, but however you can use getIntent()
method of ShareCompat and then set ClipData
accordingly. as shown in the below code snippet.
And then share intent using Intent.createChooser()