Passing Google Play Review in 15 Minutes with Sensitive Android Permissions
If you've ever submitted an Android app requiring QUERY_ALL_PACKAGES or an AccessibilityService to the Google Play Store, you probably know the dread: weeks of waiting, automated policy rejections, or vague emails demanding compliance videos.
Today, we submitted Gravity—a distraction-free, air-gapped minimalist launcher—requiring three heavily scrutinized permissions:
-
android.permission.QUERY_ALL_PACKAGES(for the A–Z App Drawer and on-device app search) -
android.permission.BIND_ACCESSIBILITY_SERVICE(for double-tap to lock while preserving biometric unlock) -
android.permission.FOREGROUND_SERVICE_SPECIAL_USE(for mindful session budgets with a top progress overlay)
Google gave us the standard "review can take up to 7 days" warning. 15 minutes later, it was approved.
Here is the exact blueprint we followed so you can get through review on your first try.
1. In-App Prominent Disclosure BEFORE the System Dialog
Google's policy for non-accessibility tools using AccessibilityService is strict: you must display a prominent, dedicated disclosure dialog inside the app before the user is taken to Android's Accessibility Settings.
Here is what works:
- Explain why you need it in plain English.
- Explicitly state what is NOT collected (no keystrokes, no screen content, no personal data).
- Do not proceed until the user explicitly taps "Enable in Settings".
// Gravity's Double-Tap to Lock Disclosure Text( text = "To lock the screen while keeping your biometric fingerprint and face unlock working, " + "Android requires the Accessibility permission.\n\n" + "Gravity strictly uses this to perform the screen-off action. " + "Zero personal data, keystrokes, or screen contents are accessed, collected, or transmitted." ) Also, in your accessibility_service_config.xml, configure empty event types to prove you aren't listening to user touches or typing:
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/accessibility_service_description" android:accessibilityEventTypes="" android:accessibilityFeedbackType="feedbackGeneric" android:canPerformGestures="false" /> 2. Purge Every Unused Permission in the Manifest
Before submitting, audit your merged AndroidManifest.xml. If you have unused high-risk permissions lingering around, automated scanners will flag your build before a human reviewer even looks at your declarations.
For example, we discovered an unused <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />. On Android 14+, this is restricted solely to alarms and incoming calling apps. Removing that single unused line saved us an instant rejection.
3. One Comprehensive 90-Second Video (With Timestamps)
Google Play Console asks for video proofs across separate declaration questionnaires. You do not need to create 3 separate videos.
Instead, record one single continuous mobile screen recording (under 90 seconds), upload it to YouTube as Unlisted, and paste the same URL across all declaration forms.
Here is the exact 86-second demo video we submitted and got approved with:
(Or watch directly on YouTube: Gravity Permissions Demo)
In the video description, provide clear timestamps that map directly to Google's questions:
-
0:20-QUERY_ALL_PACKAGES: Show the app drawer and instant device search. -
0:26-BIND_ACCESSIBILITY_SERVICE: Show the in-app disclosure dialog, then system settings, then double-tap locking the device. -
0:45-FOREGROUND_SERVICE_SPECIAL_USE: Launch a budgeted app, show the active top progress line, and pull down the notification shade to reveal the foreground notification.
4. A Tricky Gotcha: Small Notification Icons
While verifying our foreground service notification, we hit a subtle issue: the top progress line appeared, but the notification shade remained empty.
The culprit: We used an <adaptive-icon> XML (R.mipmap.ic_launcher) as the notification small icon. In modern Android, SystemUI requires the small icon to be a flat 2D monochrome vector or bitmap. Passing an adaptive icon caused SystemUI to drop the notification view silently.
Swapping it to a dedicated vector drawable immediately resolved it:
val notification = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.ic_launcher_foreground) // Flat vector, not adaptive icon! .setContentTitle("Mindful budget: $currentAppLabel") .setOngoing(true) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() 5. Air-Gapped Privacy is Your Best Defense
Reviewers scrutinize sensitive permissions because of data exfiltration risks. Gravity omits android.permission.INTERNET entirely. When your app physically lacks the capability to send bytes off the device, Google's Data Safety team can verify your claims with zero ambiguity.
Check Out Gravity
If you're looking for an intentional, text-focused Android launcher with zero telemetry and air-gapped privacy:
- 🌐 Official Website: shivamgravity.com/products/gravity
- 🧪 Join Closed Testing: Google Play Opt-In Program
- 📱 Play Store Listing: Gravity on Google Play
Community Wisdom & Further Reading
As Thomas Künneth noted in his guide on dealing with sensitive permissions, Android's privacy framework demands transparency and least privilege. Similarly, if you ever face review hurdles, the checklist in My Google Play App Update Was Rejected offers a great debugging workflow.
Keep your disclosures prominent, your video tight, and your permissions pruned, and the Play Console review process can actually be painless!