Skip to content
7 min read Guides Android

Google Play In-App Review API: Asking for Ratings on Android

Ratings shape how your app does on Google Play, and Google gives you a way to ask for them without sending people out of your app. The Play In-App Review API shows a card where the user picks one to five stars and can add a comment, and the review goes to the Play Store. It takes a few lines of Kotlin. The harder parts are the quota, the timing, and testing it at all. This guide covers each, as of 30 September 2026, using Google's own Android developer pages.

The short version

  • Create a ReviewManager, call requestReviewFlow() to get a ReviewInfo, then pass it to launchReviewFlow().
  • Google enforces a time-bound quota, so the dialog may not appear. The API never tells you whether it did.
  • Never trigger it from a button. For a permanent "Rate this app" entry, send people to your store listing.
  • Don't ask any question before or while the card shows, not even whether people like the app.
  • Test through the internal test track or internal app sharing, and use FakeReviewManager in unit tests.

What the API needs

As of 30 September 2026, Google's overview, Google Play In-App Reviews API, says in-app reviews work on Android devices running Android 5.0 (API level 21) or higher with the Google Play Store installed, which includes phones, tablets and TVs with Google TV, and on ChromeOS devices with the Play Store. The library is part of the Google Play Core libraries. Google's Kotlin and Java guide gives the Gradle lines: com.google.android.play:review, plus com.google.android.play:review-ktx for Kotlin extensions. Check that page for the current version.

The code

The flow has two steps. requestReviewFlow() asks Play for a ReviewInfo object, and launchReviewFlow() shows the card with it. Google notes that a ReviewInfo is valid for a limited time, so request it shortly ahead, but not until you are sure you will launch the flow. Here is that pattern for a fictional hiking app, preparing while the hike summary loads and launching once the summary is on screen:

import android.app.Activity
import android.util.Log
import com.google.android.play.core.review.ReviewInfo
import com.google.android.play.core.review.ReviewManagerFactory

class ReviewPrompter(activity: Activity) {
    private val manager = ReviewManagerFactory.create(activity)
    private var reviewInfo: ReviewInfo? = null

    // Call when you have decided to ask, for example as a hike summary loads.
    fun prepare() {
        manager.requestReviewFlow().addOnCompleteListener { task ->
            if (task.isSuccessful) {
                reviewInfo = task.result
            } else {
                Log.w("Review", "requestReviewFlow failed", task.exception)
            }
        }
    }

    // Call at a natural pause. Never from a button.
    fun launch(activity: Activity, onDone: () -> Unit) {
        val info = reviewInfo ?: return onDone()
        manager.launchReviewFlow(activity, info).addOnCompleteListener {
            // Play does not say whether the card appeared or the user rated.
            reviewInfo = null
            onDone()
        }
    }
}

Two rules from Google's guide are built into that sketch. The completion listener tells you the flow has finished, not what happened in it: the API doesn't indicate whether the user reviewed, or even whether the dialog was shown. And if something goes wrong, don't tell the user or change your app's flow. Carry on as normal once the listener fires.

The quota, and why the dialog may not show

Google's overview says Play enforces a time-bound quota on how often a user can see the review dialog. Calling launchReviewFlow more than once in a short period, which Google's example puts at less than a month, might not show a dialog. The exact value is an implementation detail that Google can change without notice. Google's testing guide lists other reasons the card stays hidden:

  • the app isn't available on any track, not even internal testing;
  • the app isn't in the user's Google Play library, because they didn't install it from the Play Store;
  • the primary account isn't the one selected in the Play Store;
  • the account is protected, such as an enterprise account;
  • the user has already reviewed the app;
  • the Play Store or Play services on the device has a problem, often because the Play Store was sideloaded.

So write your code on the assumption that, most of the time, nothing will appear.

When to ask, and how not to

Google's guidance on timing and design, as of 30 September 2026:

  • Ask after people have used enough of the app to give useful feedback. Finishing a level, or in a hiking app finishing a hike, is the kind of moment Google means.
  • Don't prompt too often. It frustrates people and wastes quota.
  • Ask no questions before or during the prompt. Google names opinion questions such as "Do you like the app?" and predictive ones about giving five stars.
  • Show the card as it is. Don't change its size, opacity or shape, don't put an overlay on or around it, and don't remove it in code once it appears.
  • Never from a button. Because of the quota, a "Rate us" button wired to the API may do nothing, which looks broken. Google says to redirect the user to the Play Store instead.

To that we would add: don't ask right after something failed. A sync error or a crash on the previous launch is a reason to wait.

How to test it

The dialog depends on the Play Store, so running a debug build from Android Studio on its own won't show it. Google's testing guide gives three options:

  1. Internal test track. Upload the app to the internal test track, and install it with an account that is on the testers list, is the primary account selected in the Play Store, has downloaded the app from the Play Store, and hasn't reviewed it. After that download, you can deploy new builds to the same device from Android Studio. Google notes that quota limits are not enforced for an app downloaded from the internal test track.
  2. Internal app sharing. Faster to iterate with, but reviews can't be submitted, and the submit button is disabled to make that clear.
  3. FakeReviewManager. Swap it in for ReviewManager in unit or integration tests. It doesn't draw any UI. It returns a fake ReviewInfo and reports success when you launch the flow.

Our guide to Google Play testing tracks covers setting up the internal track and internal app sharing. One more detail from Google's overview: when your app is on a closed test track, the rating and comment from this card are shared privately with you rather than published.

Flutter and React Native

Google's integration guides cover Kotlin and Java, native C++, Unity and Unreal Engine. Flutter and React Native apps reach the same API through packages that Google doesn't publish:

  • Flutter: the in_app_review plugin on pub.dev uses the In-App Review API on Android. It offers isAvailable() and requestReview() for the card, and openStoreListing() for a permanent rate button, since that call isn't limited by a quota. Its page repeats Google's advice not to trigger requestReview() from a button, and recommends testing through internal app sharing.
  • React Native: Expo's expo-store-review wraps the ReviewManager API on Android 5 and later. Call StoreReview.isAvailableAsync(), then StoreReview.requestReview(). Expo's docs also say not to call it from a button, and show how to open your Play Store listing with Linking. It works in an existing React Native app once the expo package is installed.

Whichever wrapper you use, the quota, the timing rules and the testing steps above still apply, because the card itself comes from the Play Store.

Asking for a rating is not asking for feedback

The review card does one job. It collects stars, and sometimes a comment, for your Play Store listing. It gives you no way to ask a follow-up question in the app, and no way to tell that person later that you built what they wanted. Any reply happens in public, in Play Console, as our guide to replying to Google Play reviews explains.

Google's rules also close off a common trick. An "Are you enjoying the app?" screen that sends unhappy users to a form and happy ones to the card is a question before the prompt, which Google's guidelines rule out. The better pattern is to keep two permanent entries side by side in Settings: "Rate Trailmate", which opens your store listing, and "Suggest a feature". Both are always there, for everyone, and neither filters who sees the card.

How FeedbackKit fits in

FeedbackKit is that second entry. Before you ever ask for a rating, it gives the people who want something different a place to say so: a request board inside your app where they post ideas, vote on other people's and comment. On Android it comes from the Jetpack Compose screens in the Kotlin SDK, with SDKs for Flutter and React Native too. It doesn't touch your Play ratings and doesn't show the review card.

Here is how that looks in FeedbackKit, with sample data from a fictional hiking app:

Somewhere for the wish list

The same FeedbackKit request list in an app on Mac, iPad, iPhone and Android, with users submitting requests from inside the app.

A request tells you more than a three-star review: which feature, how many people want it, and, if your app passes it through the SDK, how much monthly revenue sits behind it. When the request moves to a status in the project's email list, the person who asked is emailed, which is covered in our guide to closing the loop. If you also ship on iOS, see asking for ratings with SKStoreReviewController. And if you want the wish list in one place instead of scattered through reviews, start free.

Keep reading

Collect feedback in your own app

FeedbackKit ships SDKs for Swift, Kotlin, React Native, Flutter and JavaScript, and syncs what your users ask for into the tracker your team already uses.