Google Play Rejected Your Flutter App for Photo Permissions? Fix READ_MEDIA_IMAGES in 4 Steps (2026)

By giosaia (GSPTeck) · Published 2026-10-21 · Last verified 2026-10-21

Why did Google Play reject my Flutter app for photo and video permissions?

Because the release you uploaded, or an older one still active on a testing track, requests READ_MEDIA_IMAGES or READ_MEDIA_VIDEO, and Google Play only allows those permissions for apps whose core purpose needs broad, ongoing access to the photo library. An app that lets users pick a profile picture or attach a receipt is expected to use the system photo picker instead. In Flutter apps the permission often comes from a plugin rather than your own code. The fix is to find who adds it, remove it from the merged manifest, check the built app, and replace every active version code on every track before resubmitting.

What the policy actually says

Google’s Photo and Video Permissions policy has two parts. Apps that need broad access must pass a review and show a core use case with persistent or frequent access to photos or videos. Apps with “one-time or infrequent” use, which Google illustrates with uploading a profile picture or a photo of a cheque, should use a system picker such as the Android photo picker. The timeline on the policy page:

DateWhat changed
August 31, 2024Apps with one-time or infrequent use asked to remove the permissions and move to a picker
January 2025End of the optional extension for apps that needed more time
May 28, 2025Full compliance mandatory for all developers, including those with an extension

The same Play Console help page now also covers a Contacts Permission policy: from September 2026 apps with READ_CONTACTS are prompted to declare core use or switch to a contact picker, and compliance becomes mandatory on January 27, 2027 for apps targeting Android 17 (API level 37) or later. If you are already fixing media permissions, check contacts in the same pass.

Two columns contrasting what Google Play rejects, one-time photo uploads requesting READ_MEDIA_IMAGES or READ_MEDIA_VIDEO, with what it allows, the system photo picker or approved core gallery use
Why Play rejected the update.

Step 1: find who adds the permission

Your own AndroidManifest.xml is only one input. Gradle merges it with the manifest of every plugin, so a permission you never typed can still ship. Three ways to see the final list:

Grid of six places to find who adds a media permission: Android Studio's Merged Manifest view, apkanalyzer, plugins, old entries in your own manifest, all tracks and every active version code
Find who adds the permission.

Step 2: switch one-time picks to the photo picker

If your app picks an image now and then, you do not need a media permission at all. The image_picker package’s documentation says that on Android 13 and above it uses the Android Photo Picker, and a Flutter triager pointed out in issue 171494 that the package needs no extra permission declarations for it. Google’s Android Developers Blog adds that the photo picker has been backported to older devices, down to Android 4.4, through Google Play services. For most indie apps, a plain call is enough:

final picked = await ImagePicker().pickImage(source: ImageSource.gallery);

Test the picker on an Android 13 or newer device after removing the permission, and on one older device if you support it.

Step 3: remove the permission from the merged manifest

When a plugin declares the permission and you do not need it, override it in your app’s manifest. Android’s manifest-merge documentation describes tools:node="remove" as the way to drop an element contributed by a lower-priority manifest that is out of your control:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" tools:node="remove" />
  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" tools:node="remove" />
</manifest>

Only remove what your app does not use. If a plugin genuinely needs broad access for a feature, either replace that feature with a picker or decide whether your app’s core purpose qualifies for the declaration.

Step 4: verify, rebuild and replace every track

The rejection notice quoted in Flutter issue 173536 asks developers to remove the permissions “from all version codes within the submission. This includes both production and testing tracks.” That line catches many indie developers: the new build is clean, but an old internal or closed testing build still requests the permission.

  1. Run apkanalyzer again and confirm neither permission appears.
  2. Bump the version code and build a new app bundle.
  3. Upload it to every track that still has an older active release with the permission, including internal and closed testing.
  4. Send the changes for review from Publishing overview.

If you are in the middle of a phased release, the replacement build follows the same rules as any update; our guide to staged rollout rules for indie Flutter apps covers halting and replacing a rollout. A new closed test may also be needed if your account is still under the tester requirement described in our 12 testers for 14 days closed-testing guide.

Six-step fix: use image_picker's photo picker, remove permissions with tools:node remove, verify the build, rebuild with a new version code, replace testing builds and resubmit
The fix in six steps.

A worked example

Illustrative case. An indie habit-tracker app lets users set a profile photo and attach an image to a journal entry. Play rejects version 23. The Merged Manifest tab shows READ_MEDIA_IMAGES and READ_MEDIA_VIDEO coming from a file-opening plugin used to preview exported PDFs, not from the image code. The developer keeps image_picker for both photo features, adds two tools:node="remove" lines, confirms with apkanalyzer that the release APK no longer lists either permission, ships version 24 to production and to the closed testing track that still held version 21, and resubmits. The update is approved on the next review.

Timeline of Google Play's Photo and Video Permissions policy: August 2024 request, January 2025 extension end, May 2025 full compliance, and the contacts picker policy for 2026 and 2027
Policy timeline.

Make it part of your release routine

Permissions drift every time you add or update a plugin. Add one line to your release checklist: print the release build’s permissions with apkanalyzer and compare them with the last approved build. The same check keeps your Data safety form honest, as our guide to refreshing the Play Console Data safety form after SDK changes explains, and pairs well with the yearly target API level deadline. More of these release notes from a one-person studio are on GSPTeck’s apps and projects page.

Vertical Pinterest graphic explaining how to fix a Google Play rejection for photo and video permissions in a Flutter app
Pinterest pin: Play photo permissions rejection.

FAQ

Does image_picker need READ_MEDIA_IMAGES on Android 13?

No. On Android 13 and above image_picker uses the Android Photo Picker, which needs no media permission. If your merged manifest still lists the permission, another plugin or an old manifest entry is adding it.

Why was my app rejected when my code never asks for photo permissions?

Google Play checks the merged manifest, which includes every plugin’s declarations, and every active version code on every track. A dependency or an older testing build can carry the permission even if your current code never requests it.

Can I keep READ_MEDIA_IMAGES if my app is a gallery or photo editor?

Possibly. Apps whose core purpose needs persistent or frequent access to photos can complete the declaration in Play Console and pass a review. One-time uses such as profile pictures do not qualify.

Do I need to remove the permission from old testing builds?

Yes. The rejection notice asks for the permission to be removed from all version codes in the submission, including testing tracks, so upload a clean build to every track that still holds an affected release.

Sources