Search code examples
androidandroid-contentproviderandroid-jetpack-composeandroid-context

Take Persistable URI Permission for ACTION_SEND intent filter uri results in SecurityException


My users can select files via ACTION_OPEN_DOCUMENT

val launcher = rememberLauncherForActivityResult(
    contract = ActivityResultContracts.OpenDocument(),
    onResult = onResult
)

After which I use takePersistableUriPermission

contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)

This works great! Now the picker UI is not what I'd call optimal, so I want to also allow inverting the control flow by sharing the file with my app.

<intent-filter>
   <action android:name="android.intent.action.SEND" />
   <category android:name="android.intent.category.DEFAULT" />
   <data android:mimeType="image/*" />
</intent-filter>

And in onCreate or onNewIntent in my Activity, I want to also take the persistable URI permission.

override fun onNewIntent(intent: Intent?) {
    // null checks etc
    val uri = intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri ?: return
    contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
    // ...
}

This however, results in a SecurityException:

java.lang.SecurityException: No persistable permission grants found for UID 10146 and Uri content://com.google.android.apps.photos.contentprovider/-1/1/content://media/external/images/media/61/REQUIRE_ORIGINAL/NONE/image/jpeg/702648108

Is there a way to achieve this?


Solution

  • Is there a way to achieve this?

    Generally, no. takePersistableUriPermission() is for Storage Access Framework Uri values, as in your ACTION_OPEN_DOCUMENT scenario. It is not for arbitrary Uri values, like you might get via ACTION_PICK, or EXTRA_STREAM on receiving ACTION_SEND, or the Uri passed to ACTION_VIEW, etc.

    For ACTION_SEND, ACTION_VIEW, etc., you need to assume that your app has only transitory access to the content. You would need to have some sort of "import" operation and make your own copy of that content if you need longer-term access.