Flutter · Android
Play Store Rejections I've Actually Hit — And How I Fixed Them
· by Muhammed Shibli
Three years of shipping Flutter apps to the Play Store means I've collected a real set of rejection emails, and the pattern behind them is more useful than any generic "avoid these mistakes" checklist. Most rejections aren't about doing something forbidden — they're about a mismatch between what your app declares and what it actually does.
The rejection email that actually taught me something
Early on, I submitted an app that requested location permission for a "find nearby" feature, and it came back rejected under the permissions policy. The feature was legitimate. The problem was the Data safety section in Play Console didn't clearly explain the specific use case in language that matched what the app's runtime permission prompt said, and there was no in-app context shown to the user before the OS permission dialog appeared — the app just fired the system prompt cold. Google's review (automated, most likely, at that stage) flagged the disconnect, not the feature itself.
The fix wasn't removing the feature. It was adding a short in-app screen explaining why location was needed, right before the OS prompt, and making sure the Data safety declaration used specific, matching language instead of a vague "for app functionality" catch-all. Resubmitted, approved. That one rejection changed how I structure every permission request since: justify it visibly, in the app, before the OS asks, and make the Data safety form say the same thing.
The rejections I've hit, and what actually fixed them
Permissions and sensitive APIs. This is the one I've hit most. Any permission touching location, contacts, SMS, or call logs gets extra scrutiny, and the fix is almost always the same: an in-app explanation shown before the system dialog, and a Data safety declaration that specifically matches the feature, not a generic boilerplate answer. Vague permission justifications are the single biggest self-inflicted wound I see developers make.
Broken functionality. Google's automated testing (and sometimes a human reviewer) actually opens the app and taps around. I had a submission rejected once because a payment confirmation screen threw an error on a specific test device configuration — worked fine on my test devices, broke on theirs. The fix was testing on a wider range of emulated screen sizes and Android versions before submitting, not just my personal device. Since then, every app I ship gets tested on at least three different API levels and screen densities before it goes anywhere near Play Console.
Impersonation and deceptive behavior. This one's stricter than most developers expect, and it's not just about literally copying another brand. An app icon or name too close to an established brand, or misleading store listing screenshots that don't match the actual app experience, both fall under this. I keep listing screenshots as close to literal app screens as possible now — no heavily mocked-up marketing images pretending to be screenshots — specifically because of a near-miss on this policy early on.
Target API level. This one doesn't show up as a rejection at first submission — it shows up months later as a warning, then a restriction on new installs, if an app's target SDK falls behind Google's rolling requirement (roughly, within about a year of the current Android release). It's caught more than one client's older app off guard when they hadn't touched it in over a year and suddenly couldn't get updates through until the target API was bumped and the app retested against the new behavior changes that come with it.
The policy that's gotten stricter every year
If there's one trend across three years of doing this, it's that the Data safety section and permissions policy enforcement has gotten meaningfully stricter, not looser. What used to pass with a generic justification now needs specific, feature-matched language. What used to be a soft warning is now a hard block on some permission categories. I don't expect this trend to reverse — if anything, expect the bar to keep rising, especially around location and any permission that touches user data Google considers sensitive.
The practical response isn't to avoid sensitive permissions altogether when a feature genuinely needs them. It's to treat the Data safety form and in-app justification as part of the actual feature, not paperwork you fill out after the code is done. I now write the Data safety answers at the same time I write the permission-request code, so they can't drift apart.
The resubmission that's actually a fresh review, not a quick fix
One thing worth setting expectations on: a rejected app doesn't get a lightweight "just check the fix" re-review — a new submission goes back through essentially the same process as the first one, automated checks and possibly manual review included. This means a rejection isn't a five-minute delay even after you've fixed the actual problem; it's a full review cycle again, which for a new app can take meaningfully longer than an update to an established one. Budgeting review time into a launch date, with a buffer for at least one possible rejection round, has saved me from more than one uncomfortable "the app isn't live yet" conversation with a client expecting same-day approval.
How I structure submissions now to avoid the back-and-forth
A few habits that have cut my rejection rate close to zero over the last couple of years of client work. Every sensitive permission gets an in-app "why we need this" screen before the OS prompt, no exceptions, even when it feels like overkill for an obvious use case. The Data safety form gets filled out feature-by-feature, matching the actual runtime behavior, not copy-pasted boilerplate. Every build gets tested across a spread of Android API levels and screen sizes before submission, because "worked on my device" has burned me before and I don't trust it anymore. And target SDK gets checked against Google's current requirement as a standing item, not something I only think about when a client mentions their app stopped showing up in search.
None of this is complicated. It's just the difference between treating store submission as a formality at the end of a build versus treating it as part of the build itself — see Flutter and mobile app development for how I handle the full path from code to a live store listing, including the resubmission cycles when they happen.
Frequently asked questions
How long does Play Store review actually take?
Usually within a day for updates to an established app, but a new app's first submission can take longer, sometimes several days, especially if it touches a sensitive permission category that triggers manual review. Rejections restart the clock, which is the real cost — a rejection on day three means you're resubmitting and waiting again, not just fixing and instantly relaunching.
What's the most common reason apps get rejected on the Play Store?
In my experience, permissions policy violations — requesting a sensitive permission (location, contacts, SMS) without a Data safety section explanation that matches how the app actually uses it, or without an in-app justification prompt. It's rarely because the permission itself is disallowed; it's because the declared use doesn't line up with what the app is seen doing.
Can a rejected app be resubmitted immediately?
Yes, there's no cooldown period — but resubmitting the exact same build with the exact same issue just gets rejected again, sometimes faster than the first time because the reviewer (or automated system) already has context. Read the rejection reason carefully, actually fix the root cause, and note what changed in your resubmission notes.
Does target API level really get apps removed from the Play Store?
Yes, and this trips up more small apps than people expect. Google requires new apps and updates to target an API level within roughly a year of the latest Android release, and apps that fall too far behind get restricted from new installs or removed entirely. It's not a one-time submission check — it's an ongoing requirement that catches apps nobody's updated in a while.
Related reading
Keep going
Pinned
When a Flutter App Needs Native Kotlin (A Real Example)
Why I built a caller ID app in native Kotlin instead of Flutter — CallScreeningService, platform channels, and the honest rule I use now for when Flutter isn't the right tool.
- Flutter
- Android
Pinned
Suraj Education — School App with Live Bus Tracking
A school management app where parents watch the school bus move on a live map.
- Flutter
- Android
Pinned
Flutter App Development Cost in India by App Type (2026 Breakdown)
What Flutter app development actually costs in India, broken down by app type — booking, delivery, streaming, marketplace — plus the store and infrastructure costs nobody budgets for upfront.
- Flutter
- Business