I'm little bit puzzled about grantUriPermission function. I'd like to use it to grant file access to another application via a FileProvider. Since FileProvider must be local (non-exported) for good reason, I must grant the other app temporary read/write permission. Documentation says:
Normally you should use Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION with the Intent being used to start an activity instead of this function directly. If you use this function directly, you should be sure to call revokeUriPermission(Uri, int) when the target should no longer be allowed to access it.
Fair enough, since I don't need to open an activity nor explicitly start a service (the other app would just ask for that file when its time comes), I though I'm fine with just plain:
Uri newFileUri = FileProvider.getUriForFile(this, AUTHORITY, file);
grantUriPermission(OTHER_APP_PACKAGE_NAME, newFileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
To my surprise, I was still getting the security exception:
java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{42ee0b98 5878:example.com.myapplication3/u0a82} (pid=5878, uid=10082) that is not exported from uid 10081
After few experiments I found out that I must call the other app via an Intent at least once:
Intent intent = new Intent();
intent.setClassName(OTHER_APP_PACKAGE_NAME, OTHER_APP_SERVICE_NAME);
startService(intent);
As soon as I do this, I can do everything as expected -- I can remove this intent code, I can even reinstall both apps and it still works (!). It seems like there's a hidden requirement that the owner must call the other app at least once and its stored somewhere in the system.
Is this documented somewhere?
EDITED: first I thought I have to use Intent.FLAG_GRANT_READ_URI_PERMISSION flag, too but this seems to be not necessary.