Why Google Play Rejects Apps and How to Avoid It

Editorial team
Dot
July 9, 2026
An educational mobile app development infographic titled "Why Google Play Rejects Apps and How to Avoid It," with the subtitle "Understand the top rejection reasons and follow proven best practices to get your app approved—faster." The layout features a central 3D smartphone mockup showing the Google Play Store logo surrounded by UI icons like a checklist, a bug, and a warning symbol. The left side details "Top Reasons for Rejection," including Policy Violations, Poor User Experience, Misleading Content, Permissions Issues, and Content Restrictions. The right side outlines "How to Avoid Rejection" with steps like Follow Policies, Test Thoroughly, Be Transparent, Use Permissions Wisely, and Keep Content Appropriate. A bottom horizontal banner features a 5-step "Best Practices for Approval" workflow: Pre-Launch Checklist, Quality First, Clear Descriptions, Keep It Updated, and Monitor & Respond.

You spent three months building your app. You tested it. You polished it. You submitted it. Then came the email: “Your app has been rejected.”

No clear fix. No direct support. Just a policy link and a deadline. Here is exactly how to make sure it never happens again.

Introduction

Google Play is the world’s largest app marketplace with over 3.5 billion active Android devices and more than 2.5 million apps listed as of 2025. Getting your app onto the Play Store is not just about writing good code; it is about understanding a detailed, frequently updated set of policies that Google enforces both automatically and manually.

Every year, Google increases the sophistication of its automated review pipeline. In 2023, Google reported removing 2.28 billion policy-violating apps and banning 333,000 developer accounts. In 2024, it expanded its AI-assisted review to catch deceptive metadata and hidden data collection at scale.

The good news: most rejections are entirely preventable. The reasons are consistent, the fixes are well-documented, and the patterns are clear once you know what to look for.

This guide covers every major rejection category, the corresponding policy section, and the concrete fix.

Problem Statement: Why Rejections Are So Painful

Google Play rejections hit developers in three ways:

  • Time loss. A rejection can delay your launch by days or weeks. The review cycle is not instant; re-submissions after a rejection typically take an additional 3–7 days.
  • Account risk. Repeated violations escalate from app rejection → app removal → developer account termination. A terminated account loses all apps, all revenue, and all user reviews permanently.
  • Opacity. Google’s rejection emails reference policy pages rather than specific lines of your app. Without knowing which exact behavior triggered the flag, developers often fix the wrong thing and resubmit incorrectly.

Understanding the specific, documented reasons behind rejections is the only reliable way to avoid them.

 

How Google Play Reviews Apps

Before diving into the reasons for rejection, it helps to understand who actually reviews your app.

Google’s Three-Layer Review System

Review timelines:

  • New apps: 3 - 7 days
  • Updates to existing apps: 2 - 48 hours (faster for established, clean-history accounts
  • Apps flagged by automation: can extend to 2+ weeks for human review

 

The 10 Most Common Rejection Reasons (and How to Fix Them)

 

Reason 1: Missing or Inadequate Privacy Policy

Policy Reference: Google Play User Data Policy

Why it triggers rejection: Any app that collects, transmits, or handles personal data, including device identifiers, location, contacts, camera, microphone, or usage data, must have a publicly accessible privacy policy linked in both the app and the Play Store listing. This is enforced for all apps regardless of category.

What “inadequate” means:

  • A generic template that does not match your actual data practices 
  • A broken or 404 URL 
  • A policy hosted behind a login wall - No mention of third-party SDKs (Firebase, Ads, Analytics) that collect data.

Fix :

In your Play Console store listing:

Store Listing → App Content → Privacy Policy → Enter URL

In your app (required for apps targeting users who may be under 13 or in the EU):

 // Show privacy policy link on first launch or in settings
 val privacyPolicyUrl = "https://yourapp.com/privacy"

fun openPrivacyPolicy(context: Context) {
   val intent = Intent(Intent.ACTION_VIEW, Uri.parse(privacyPolicyUrl))
   context.startActivity(intent)
 }

Privacy policy must include: 

  • What data do you collect
  • Why do you collect it 
  • Who you share it with (list every third-party SDK)
  • How users can request deletion 
  • Your contact information

Important: A privacy policy URL that returns a 404 or redirects to a login page is treated the same as having no policy at all. Test the URL from an incognito browser before submitting.

Reason 2: Incomplete or Inaccurate Data Safety Section

Policy Reference: Data Safety Section Requirements

Why it triggers rejection: Google requires every app to accurately declare in the Play Console's Data Safety form what data it collects, why it collects it, and whether it is shared with third parties. Mismatches between your declaration and your app’s actual behavior (detected via static analysis) trigger rejection.

Common mistakes: 

  • Declaring “no data collected” while using Firebase Analytics or Crashlytics
  • Not declaring advertising ID collection when using AdMob 
  • Missing location data declaration when using the Fused Location Provider

Fix: Data Safety section categories to check:

Play Console → App Content → Data Safety

Data Collection Table
Data Type Collected If You Use
Device or other IDs Firebase, AdMob, any analytics SDK
Location (approximate) Maps, geofencing, weather
Location (precise) GPS navigation, ride sharing
Contacts Any contact picker or sync
App activity Firebase Analytics, custom event tracking
Crash logs Crashlytics, Sentry, Bugsnag
Personal info (name/email) Login, user profiles
Financial info In-app purchases, payment forms

How to audit your declared data programmatically:

 // Check which permissions your app declares vs what you report in Data Safety
 // Run this in debug builds to print all declared permissions
 fun logDeclaredPermissions(context: Context) {
   val packageInfo = context.packageManager.getPackageInfo(
       context.packageName,
       PackageManager.GET_PERMISSIONS
   )
   packageInfo.requestedPermissions?.forEach { permission ->
       Log.d("DataSafety", "Declared permission: $permission")
   }
 }

Source: Google Play Help Data Safety Section · How the Data Safety card appears to users when an app shares data · 2026 

Source: Google Play Help Data Safety Section · Data Safety card when an app declares it collects no data · 2026 

Source: Google Play Help Data Safety Section · Data Safety card when data is collected but not shared with third parties · 2026 

Reason 3: Target API Level Below Google’s Minimum Requirement

Policy Reference: Target API Level Requirements

Why it triggers rejection: Google enforces a minimum targetSdkVersion for all app submissions. Apps that do not meet the requirement are rejected outright, regardless of content.

2025 Requirements: | Submission Type | Minimum targetSdkVersion | |—|—| | New apps | API 34 (Android 14) | | Existing app updates | API 34 (Android 14) | | Wear OS apps | API 34 | | Android TV apps | API 34 |

Fix : Update build.gradle (Groovy):

android {
   compileSdk 35  // Android 15


   defaultConfig {
       applicationId "com.yourcompany.yourapp"
       minSdk 24               // Android 7.0 minimum (recommended)
       targetSdk 34            // Android 14 — minimum required for 2025
       versionCode 12
       versionName "2.1.0"
   }
 }

Fix: Update build.gradle.kts (Kotlin DSL):

android {
   compileSdk = 35


   defaultConfig {
       applicationId = "com.yourcompany.yourapp"
       minSdk = 24
       targetSdk = 34          // Must be 34+ for Play Store submissions in 2025
       versionCode = 12
       versionName = "2.1.0"
   }
 }

After updating targetSdk, test for behavioral changes:

# Run lint to catch targetSdk compatibility issues
./gradlew lint


# Check for deprecated API usage
./gradlew lintDebug --stacktrace

Important: Raising targetSdk is not just a number change to a number. Android 12+ introduced exact alarm restrictions, Android 13+ changed notification permissions, and Android 14+ enforces foreground service types. Test thoroughly before re-submitting.

Reason 4: Dangerous Permissions Without Justification

Policy Reference: Permissions Policy

Why it triggers rejection: Google classifies certain permissions as “dangerous” they require explicit user consent at runtime and must be justified by your app’s core functionality. Declaring permissions your app does not genuinely need is a direct policy violation.

Commonly flagged permissions:

Permission Mistakes Table
Permission Common Mistake
READ_CONTACTS Declared but only used for a one-time share feature
ACCESS_FINE_LOCATION Used when ACCESS_COARSE_LOCATION would suffice
RECORD_AUDIO Declared in manifest but feature never launched
READ_CALL_LOG Triggers automatic enhanced review — requires approval
CAMERA Declared but only used for profile photo upload via intent
BACKGROUND_LOCATION Requires a dedicated approval form + a compelling use case

Fix : Use intent-based alternatives where possible:

// 
// ❌ BAD — Requesting CAMERA permission just to capture a photo
// Requires full camera permission + policy justification


// ✅ GOOD — Use the system camera intent (no permission needed)
fun openCameraWithIntent(launcher: ActivityResultLauncher<Uri>, photoUri: Uri) {
  val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply {
      putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
  }
  launcher.launch(photoUri)
}


// ✅ GOOD — Use photo picker (no READ_MEDIA_IMAGES permission needed on Android 13+)
fun openPhotoPicker(launcher: ActivityResultLauncher<PickVisualMediaRequest>) {
    launcher.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}

Fix: Request only the permission level you need:

<!-- AndroidManifest.xml -->


<!-- ❌ BAD — Precise location when you only need approximate -->
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> -->


<!-- ✅ GOOD — Request coarse only if that's all your feature needs -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />


<!-- ✅ GOOD — If you need fine, declare both and let the user choose on Android 12+ -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Fix: Remove permissions your app does not use:

# Find all permissions declared in the merged manifest
./gradlew :app:processDebugManifest


# Review the merged manifest output
cat app/build/intermediates/merged_manifest/debug/AndroidManifest.xml | grep "uses-permission"

Source: Android Developers Manage Manifest Files · Official diagram showing how Android merges manifests from app + libraries at build time · 2026 

Source: Android Developers Manage Manifest Files · The Merged Manifest tab in Android Studio left pane shows merged output, right pane shows which file contributed each permission · 2026 

Reason 5 : App Crashes or ANRs Detected in Pre-Launch Report

Why it triggers rejection: Google’s automated Robo tester runs your app on real devices via Firebase Test Lab before review. If it detects crashes (force closes) or ANRs (Application Not Responding UI thread blocked for 5+ seconds), your app may be rejected or flagged with quality warnings.

Fix : Run the pre-launch report locally before submitting:

# Run baseline profile + startup check
./gradlew :app:connectedDebugAndroidTest


# Run Firebase Test Lab from CLI (requires gcloud setup)
gcloud firebase test android run \
--type robo \
--app app/build/outputs/apk/release/app-release.apk \
--device model=Pixel6,version=34,locale=en,orientation=portrait \
--timeout 90s

Fix: Detect and handle ANRs with StrictMode in debug builds:

class MyApplication : Application() {


  override fun onCreate() {
      super.onCreate()


      if (BuildConfig.DEBUG) {
          // Catch main-thread disk/network violations before they become ANRs
          StrictMode.setThreadPolicy(
              StrictMode.ThreadPolicy.Builder()
                  .detectDiskReads()
                  .detectDiskWrites()
                  .detectNetwork()
                  .penaltyLog()
                  .penaltyFlashScreen()
                  .build()
          )
      }
  }
}

Source: Google Play Console Pre-Launch Reports · Example of an EditText accessibility issue flagged by the automated Robo tester before submission · 2026 

Source: Google Play Console Pre-Launch Reports · Accessibility label issues detected in the pre-launch report · 2026 

Fix: Move heavy work off the main thread:

// ❌ BAD — SharedPreferences read on main thread (triggers StrictMode + potential ANR)
val token = sharedPreferences.getString("auth_token", null)


// ✅ GOOD — Use DataStore (async) instead of SharedPreferences
val tokenFlow: Flow<String?> = context.dataStore.data.map { prefs ->
  prefs[AUTH_TOKEN_KEY]
}


// Collect in a coroutine, never on the main thread
viewModelScope.launch {
  tokenFlow.collect { token ->
      // use token safely
  }
}

Reason 6: Misleading Metadata (Title, Description, Screenshots)

Why it triggers rejection: 

Google’s human review team checks that your store listing accurately represents your app. Common violations include:

  • Keyword stuffing in the title or description (e.g., “Calculator — best free calculator math calculator 2025”)
  • Screenshots that don’t match the actual app UI
  • Fake review solicitation language in the description (“Rate us 5 stars!”)
  • Claiming features your app does not have (“AI-powered” when it’s a static list)
  • Impersonating other apps with similar names, icons, or screenshots

What Google checks:

App Title → Max 50 characters. No keyword stuffing. Must match app function.
Short Description → Max 80 characters. No promotional superlatives.
Full Description → Max 4,000 characters. Must reflect actual app features.
Screenshots → Must show actual app UI. No device frames that mislead the screen size.
App Icon → Cannot resemble system icons or other popular apps.

Fix: Title and description checklist:

 ✅ Title: "Budget Tracker – Expense Manager"       (clear, accurate, 34 chars)
 ❌ Title: "Budget Tracker – Best FREE Money App Expense Finance 2025" (stuffed)

✅ Description: Start with the core value proposition.
             List actual features with honest capability claims.
             No "Download now!" "Best in class", or star rating requests.

 ✅ Screenshots: Capture from a real device or emulator running your actual app.
             Match the device frame to the screenshot device type.
             Include at least one screenshot per major feature.

Source: Google Blog How to Resolve Google Play Policy Issues · Official Google guidance on identifying and fixing metadata and content policy violations · 2026 

 

Reason 7: Content Rating Questionnaire Mismatch

Policy Reference: App Content Rating

Why it triggers rejection: Every app must complete the IARC content rating questionnaire in Play Console. If your app contains content that contradicts your stated rating, violence, mature themes, or user-generated content with no moderation, Google rejects it.

Common mistakes: 

  • Selecting the “Everyone” rating but allowing unrestricted user-generated content
  • Enabling social features (chat, forums) but declaring no interactive elements
  • Containing any reference to real-money gambling without a valid license declaration.

Fix: Complete the rating questionnaire accurately:

Play Console → App Content → App Content Rating → Start Questionnaire

Key questions that trip developers up:

App Questionnaire Table
Question Answer "Yes" if your app has...
User-generated content Chat, comments, reviews, forums, profile uploads
Location sharing Real-time location visible to other users
Purchasing Any in-app purchase or subscription
References to controlled substances Any mention of alcohol, tobacco, drugs
Violence Combat, weapons, blood — even cartoon
Gambling simulations Slot machines, poker — even with fake currency

 

Reason 8: Foreground Service Type Not Declared (Android 14+)

Why it triggers rejection: Android 14 (API 34) made foreground service type declarations mandatory. Apps targeting API 34+ that use foreground services without a declared type crash at runtime and are rejected by the automated scanner.

Fix: Declare foreground service type in AndroidManifest.xml:

<!-- AndroidManifest.xml -->
<manifest>


  <!-- Required permission for each service type used -->
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  <uses-permissionandroid:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />


  <application>


      <!-- ✅ CORRECT — Declare the type attribute on your service -->
      <service
          android:name=".MusicPlayerService"
          android:foregroundServiceType="mediaPlayback"
          android:exported="false" />


      <!-- ✅ For location tracking services -->
      <service
          android:name=".LocationTrackingService"
          android:foregroundServiceType="location"
          android:exported="false" />


  </application>
</manifest>

Fix : Start foreground service with matching type in Kotlin:

// ✅ API 34+ — Must pass service type when calling startForeground()
class MusicPlayerService : Service() {


  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
      val notification = buildNotification()


      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
          // Pass the service type that matches your manifest declaration
          startForeground(
              NOTIFICATION_ID,
              notification,
              ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
          )
      } else {
          startForeground(NOTIFICATION_ID, notification)
      }


      return START_STICKY
   }
 }

Valid foreground service types for API 34+:

Foreground Service Types Table
Type Use Case
camera Camera access in the background
connectedDevice Bluetooth / USB device connection
dataSync Background data sync
health Fitness/health monitoring
location Background location tracking
mediaPlayback Audio/video playback
mediaProjection Screen recording
microphone Background audio recording
phoneCall VoIP calls
remoteMessaging Messaging apps
shortService Short-lived background tasks (max 3 min)
specialUse Custom use case — requires justification in the manifest
systemExempted System-granted exemption only

 

Reason 9 : Sensitive App Category Without Required Declaration

Policy Reference: Financial Services Policy | Health & Medical Policy

Why it triggers rejection: Apps in regulated categories require additional declarations and sometimes pre-approval before they can be listed.

Categories requiring special declarations:

App Categories and Requirements Table
Category Requirement
Financial services (lending, investment) Must complete the Financial Services declaration form; lending apps need a government license number
Real-money gambling Country-specific license required; cannot be approved in most regions
VPN apps Must complete VPN declaration; cannot traffic-sniff user data
Accessibility services Must use AccessibilityService only for declared accessibility features
SMS / Call Log access Requires Default SMS App or specific approved use case
Device Admin apps Must be a legitimate MDM — no consumer apps
Health & fitness (medical claims) Cannot make diagnostic or treatment claims without regulatory approval

Fix : Check if your app falls into a sensitive category:

Play Console → App Content → App Content → scroll to "Sensitive App Content" declarations

Source: Google Play Console · The Policy Center within Play Console, where sensitive category declarations and compliance deadlines are managed · 2026 

Reason 10 : Intellectual Property Violation

Why it triggers rejection: Google’s systems and human reviewers check for trademark infringement in app names, package names, icons, screenshots, and descriptions.

Common violations: 

  • Using another company’s brand name in your app title (“WhatsApp Backup Manager”) 
  • An icon that closely resembles a major app’s logo
  • Screenshots showing competitor app UI - Using copyrighted music in demo videos

Fix : Pre-submission IP checklist:

App Name → Search USPTO (US) or EUIPO (EU) trademark databases before naming
Package Name → Use your own company domain: com.yourcompany.yourapp
App Icon → Original design; run reverse image search to check similarity
Screenshots → Only show your own app UI; blur or remove any third-party content.
Description → Do not mention competitor app names unless for legitimate comparison.
Audio/Video → Use only royalty-free or original content in the preview video.s

 

Pre-Submission Checklist: Run This Before Every Release

TECHNICAL

  • targetSdkVersion ≥ 34 in build.gradle
  • All foreground services have a type declared (API 34+)
  • Lint passes with no errors: ./gradlew lint
  • No crashes on Pixel 6 emulator (API 34) cold start
  • StrictMode passes in debug build (no main-thread disk/network)
  • APK/AAB built with release signing (not debug keystore)

PERMISSIONS

  • Every permission in AndroidManifest.xml is actively used
  • Dangerous permissions have a runtime request dialog with rationale
  • No READ_CALL_LOG, PROCESS_OUTGOING_CALLS, or SMS permissions unless genuinely needed
  • BACKGROUND_LOCATION uses the two-step permission request flow

STORE LISTING

  • Title ≤ 50 characters, no keyword stuffing
  • The description accurately represents all features
  • Screenshots taken from actual device/emulator (not mockups with fake data)
  • Content rating questionnaire completed and accurate
  • Privacy policy URL is live, public, and loads without login

DATA SAFETY

  • All third-party SDKs (Firebase, AdMob, Crashlytics) are declared in Data Safety.
  • Location data collection is declared if any location API is used
  • "Data shared with third parties" accurately reflects SDK data practices
  • Data deletion request contact/link provided if collecting personal data

COMPLIANCE

  • No trademarked names in title, icon, or description
  • The app icon is original and does not resemble another major app's icon
  • No solicitation of ratings in the app or description
  • No fake or incentivized review language

Source: Google Play Console · The “Release with Confidence” section of Play Console shows quality signals before you publish · 2026 

 

What to Do When Your App Gets Rejected

Step 1 : Read the Rejection Email Carefully

Google’s rejection emails include: 

  • The policy section that was violated
  • A deadline to appeal or resubmit (typically 30 days)
  • In some cases, specific examples from your app.

Step 2 : Map the Violation to Your App

Policy cited in email
      │
      ▼
Read the full policy page linked in the email.l
      │
      ▼
Identify every place in your app that could trigger that policy
      │
      ▼
Fix ALL instances (not just the obvious one — reviewers check everything)
      │
      ▼
Re-test on a clean device with no prior app install
      │
      ▼
Re-submit with an accurate update summary in the release notes

Step 3 : Appeal If You Disagree

If you believe the rejection is incorrect:

Play Console → Inbox → Select rejection email → "Appeal" button

Write a clear, factual explanation referencing the specific policy

Attach screenshots proving compliance

Do NOT resubmit the same app without changes and expect a different result

Appeals are reviewed by a different team from the original review

Important: Do not attempt to create a new developer account to resubmit a rejected app. Google links accounts by payment method, device, and IP address. Creating a secondary account after a rejection or ban violates the Developer Distribution Agreement and results in permanent termination of all associated accounts.

Key Takeaways

Privacy policy is non-negotiable: any app that handles user data must have one, publicly accessible, accurately written.

Data Safety must match reality: Google’s scanners detect SDK usage and compare it to your declaration; mismatches are caught


targetSdkVersion 34 is the 2025 floor
: update it or your submission is rejected before a human sees it


Only request permissions you actually use
: audit your merged manifest before every release


Foreground service types are mandatory on API 34+
: no type declaration = crash = rejection


Metadata matters as much as code
: misleading titles, stuffed descriptions, and mismatched screenshots are policy violations


Sensitive categories need declarations
: financial, VPN, health, and accessibility apps have extra requirements


Rejections are not bans
: fix the specific issue, re-test completely, and re-submit confidently

 

Conclusion

Getting rejected by Google Play is frustrating, but it is rarely random. Every rejection maps to a documented policy, and every policy has a clear fix.

The teams that consistently ship without rejection share one habit: they treat the Play Store policies as part of their development process, not an afterthought at submission time. They audit permissions before writing code that needs them. They fill out the Data Safety form when they add a new SDK. They run their app through the pre-launch report before every major release.

Build that habit, and the Play Store review process becomes a formality rather than a gatekeeping nightmare.

Your app is ready. Now make sure Google agrees.

Reference Links

Official Google Documentation

SDK & API References

Tools

FAQ’s

No items found.

Actionable Insights,
Straight to Your Inbox

Subscribe to our newsletter to get useful tutorials , webinars,use cases, and step-by-step guides from industry experts

Start Pushing Real-Time App Updates Today
Try AppsOnAir for Free
Stay Uptodate