How to ask for app review android without annoying users

When and how to trigger the Android in-app review dialog using the Play Core API — with timing and context rules that improve opt-in rates without hurting retention.


The wrong way to ask for reviews (and why most apps do it)

Most apps ask for a review at the worst possible moment: immediately after first launch, during the middle of a task, or after something has just gone wrong.

The result: users tap "Not now," "Never," or — worst of all — leave an angry 1-star review saying "this app keeps asking me to rate it."

Android provides a proper API for in-app reviews. Using it correctly is the difference between a 4.6 average rating and a 3.8 average rating for otherwise identical apps.

The Play Core In-App Review API

Since Android API level 21, Google provides the Play In-App Review API (part of Play Core library). It shows a native Google Play rating dialog without ever leaving your app. The user rates 1–5 stars and optionally writes a review — all inline.

Adding the dependency

// In app/build.gradle
implementation 'com.google.android.play:review:2.0.1'
implementation 'com.google.android.play:review-ktx:2.0.1' // for Kotlin

The basic flow

val manager = ReviewManagerFactory.create(context)
val request = manager.requestReviewFlow()
request.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        val reviewInfo = task.result
        val flow = manager.launchReviewFlow(activity, reviewInfo)
        flow.addOnCompleteListener {
            // Flow has finished — the user may or may not have submitted a review
            // You cannot tell which — this is intentional by Google
        }
    }
}

Important: You cannot detect whether the user submitted a review or dismissed the dialog. Google designed it this way to prevent reward-gating (e.g. "rate us to unlock this feature").

Google's quota limits

Google Play silently suppresses the review dialog if it has been shown too recently, regardless of whether the user reviewed or not. The exact quota is not published, but the practical limit is approximately once per 30 days per user, per app install.

This means if you trigger the API at the wrong time and the user dismisses it, you may not get another chance for a month. Choose your moment carefully.

When to ask: timing rules that work

Rule 1: After a success moment

Trigger the review prompt after the user completes something meaningful. Examples by app type:

  • Habit tracker: After completing a 7-day or 14-day streak
  • Fitness app: After finishing a workout or reaching a goal
  • Productivity app: After completing their first project or closing 10 tasks
  • Game: After completing a level, winning a match, or reaching a milestone
  • Utility app: After the user has performed the core action 5–10 times

The emotional state after success ("I did it!") produces significantly better review scores than neutral moments.

Rule 2: Not on first launch

A user who has just installed your app has no basis for a review. Wait for at least 3–7 sessions or a meaningful usage milestone before asking.

Rule 3: Not during a task

If a user is in the middle of filling in a form, editing something, or reading content, interrupting them with a review prompt creates frustration. Ask at natural pause points — after saving, after completing, after returning to a home screen.

Rule 4: Not after something went wrong

If your app just showed an error, crashed and recovered, or if the user has been repeatedly tapping the same button (a sign of confusion), do not ask for a review. You'll get a 1-star.

A simple implementation pattern

Track usage in SharedPreferences or a local database:

object ReviewPromptManager {
    private const val KEY_SESSIONS = "review_sessions"
    private const val KEY_LAST_SHOWN = "review_last_shown"
    private const val MIN_SESSIONS = 5
    private const val MIN_DAYS_BETWEEN = 30L

    fun shouldShowReview(prefs: SharedPreferences): Boolean {
        val sessions = prefs.getInt(KEY_SESSIONS, 0)
        val lastShown = prefs.getLong(KEY_LAST_SHOWN, 0L)
        val daysSinceLast = (System.currentTimeMillis() - lastShown) / 86_400_000L
        return sessions >= MIN_SESSIONS && daysSinceLast >= MIN_DAYS_BETWEEN
    }

    fun recordReviewShown(prefs: SharedPreferences) {
        prefs.edit()
            .putLong(KEY_LAST_SHOWN, System.currentTimeMillis())
            .apply()
    }

    fun incrementSession(prefs: SharedPreferences) {
        val current = prefs.getInt(KEY_SESSIONS, 0)
        prefs.edit().putInt(KEY_SESSIONS, current + 1).apply()
    }
}

Call incrementSession on app open. Call shouldShowReview after a success moment. If true, trigger the API and call recordReviewShown.

What about users who gave you 1 or 2 stars?

You cannot filter by rating with the Play API — Google does not allow that. You should not attempt to direct users to an internal feedback form before rating (this is against Play policy if it gates the rating dialog).

The best strategy is to fix the problems causing low ratings and respond to reviews publicly. Developers who respond to negative reviews see measurably better long-term rating trends than those who ignore them.

Testing your review flow

Use the Play Core fake review manager for local testing:

val manager = FakeReviewManager(context) // Use in debug builds only

This shows the real dialog flow without counting against your quota.


Monitor all your Google Play and App Store reviews in one inbox with Apporb. Filter by rating, draft responses, and never miss a 1-star again.