Exploring Android 14: Partial Media Permissions

If you’ve used iOS in recent years, you’ve likely experienced the ability to grant apps partial access to your device media. I have always been a big fan of this feature, as in a lot of cases you won’t want to grant anyone access to your entire media library – being able to do so for specific media items gives you much greater control over the privacy between you and your apps.

With Android 14, this feature has come to Android – allowing users to have greater control over the privacy of their device media. The great news is that if you are using (or intent on using) the Photo Picker, then you don’t need to manually implement the support for the new partial media permissions as they are handled out of the box. If you maintain your own media picker in your app, then you’ll need to add support for this new approach to media permissions. In this blog post, we’ll run through how this works and the changes that you’ll need to make in your apps.


When it comes to partial media access, this new permission takes the form of READ_MEDIA_VISUAL_USER_SELECTED. We’ll need to start by adding this permission to our applications manifest file. This will sit alongside any of the existing media permissions that you have in your application (such as READ_MEDIA_IMAGES or READ_MEDIA_VIDEO).

<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />

Now that we have this permission in place, we’re ready to start applying changes within our application. Before we do this, let’s first understand the permissions flow and how we’re going to want to present this to the user, based on the current granted state.

As we can see in the flow above, how we handle the permissions flow is dependant on what the user has currently granted.

  • If the user has no granted any media access permissions to our application, we’re going to need to immediately trigger the permissions request
  • If the user has granted some media access, even if only partial, then we’ll want to present the media to the user. If the user has only granted partial permissions, we should not automatically request further permissions at this point
  • If the user has only granted partial access, then we’ll want to displayed something within our UI that allows the user to grant further access to media. We should not automatically request further permissions here, this should only ever be invoked by the user

This flow allows to create a smooth media selection flow, without constantly forcing the user to grant our application further permission to their device media. When it comes to checking for these permission states, we can implement something that looks like the following:

if (
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
    (
        ContextCompat.checkSelfPermission(context, READ_MEDIA_IMAGES) == PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(context, READ_MEDIA_VIDEO) == PERMISSION_GRANTED
    )
) {
    // User has granted full access to media library. 
    // We have full access to display the media on the users device and 
    // do not need to show a prompt to grant further permission
} else if (
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
    ContextCompat.checkSelfPermission(context, READ_MEDIA_VISUAL_USER_SELECTED) == PERMISSION_GRANTED
) {
    // User has granted partial access to the device media. 
    // We can display the media that we have access to, 
    // while also showing a non-blocking prompt to grant further permission
}  else if (ContextCompat.checkSelfPermission(context, READ_EXTERNAL_STORAGE) == PERMISSION_GRANTED) {
    // We have full access up to Android 12. If running below Android 13, 
    // this block will allow us to display the device media
} else {
    // No media permissions have been granted so far, we can 
    // show the permission request dialog to request partial/full media access
}

With this logic in place, we can now trigger the permission request flow. This will be dependant on the Android version that the app is being run on, but the important thing to not here is the addition of READ_MEDIA_VISUAL_USER_SELECTED for Android 14.

We’ll start here by defining an activity result listener that will be used to capture the result of our permissions request.

val requestPermissions = registerForActivityResult(RequestMultiplePermissions()) { results ->
    // Handle permissions result
}

Note: Here we area requesting both image and video access, this will be dependant on your requirements.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
    requestPermissions.launch(arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_VISUAL_USER_SELECTED))
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    requestPermissions.launch(arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO))
} else {
    requestPermissions.launch(arrayOf(READ_EXTERNAL_STORAGE))
}

When it comes to the permission flow, the user will be presented with the following alert. If selection “Select photos and videos”, the user will enter the selection screen where they can pick the media that they wish to grant access to.

Once this permission request flow has been completed, the activity result handler that we defined previously be triggered.

val requestPermissions = registerForActivityResult(RequestMultiplePermissions()) { results ->
    // handle permission request result
}

Within this block we can now trigger any code that will access the device media and display it within the UI. We won’t cover that here, but you can see an example of this in the official documentation.


Compatibility Behaviour

If you update your application to SDK 34 and do not implement these permission changes then things won’t break, but the experience will not be ideal for the user.

For example in this case, if the user selected the partial permission when presented with the permissions request, this will grant your application one-time access to this permission and any selected device media. If the user moves away from your app (e.g moves it to the background, or the system kills it), then permission will be lost and will need to be re-granted. This is not a great experience, as the user would expect the media that they previously selected to still be accessible to the application. In the case of re-selection, this is essentially the same outcome – the user must re-grant the permission to device media and follow the same flow as above.

With this in mind, it’s important to adopt this new permission behaviour within your apps that are targeting SDK 34.


As we can see, this new approach to permissions gives our user greater flexibility over the privacy of their device media. While it does require some extra checks and implementation details within our apps, the photo picker exists to make this flow much easier when implementing media support.

If you’ve already implemented these permissions in your app and love to learn more about how you got on. If you are looking to add support when you upgrade your app to Android 14, I’d love to help!

Thanks for reading! If you enjoyed this post, please consider sponsoring this blog 😊

Leave a Reply

Your email address will not be published. Required fields are marked *