A highly customizable Android library providing a dialog, which asks the user to rate the app. If the user rates below the defined threshold, the dialog will show a feedback form or ask the user to mail his feedback. Otherwise it will ask the user to rate the app in the Google Play Store.
You can also use this library to show the Google in-app review easily under certain conditions:
(Source: https://developer.android.com/guide/playcore/in-app-review)
This library:
The library supports API level 14 and higher. You can simply include it in your app via Gradle:
dependencies {
...
implementation 'com.suddenh4x.ratingdialog:awesome-app-rating:2.7.0'
}
Since version 2.4.0
you can use the Maven Central repository:
allprojects {
repositories {
...
mavenCentral()
}
}
If you want to use an older version of this library, you have to use JCenter:
allprojects {
repositories {
...
jcenter()
}
}
This library provides a builder to configure its behavior.
AppRating.Builder(this)
.setMinimumLaunchTimes(5)
.setMinimumDays(7)
.setMinimumLaunchTimesToShowAgain(5)
.setMinimumDaysToShowAgain(10)
.setRatingThreshold(RatingThreshold.FOUR)
.showIfMeetsConditions()
You should call the builder only in the onCreate()
method of your main Activity class, because every call of the method showIfMeetsConditions
will increase the launch times.
With the settings above the dialog will show up if the following conditions are met:
Furthermore the dialog will show up again if the user has clicked the later
button of the dialog and
If the rate or never button is clicked once or if the user rates below the defined minimum threshold, the dialog will never be shown again unless you reset the library settings with AppRating.reset(this)
- but doing this is not recommended.
If you have adjusted the dialog to suit your preferences, you have multiple possibilities to show it. Usually you want to show the dialog if the configured conditions are met:
ratingBuilder.showIfMeetsConditions()
This method also returns a boolean to indicate whether the dialog shows up or not. So you can prevent showing other dialogs at the same time as the rating dialog.
If you want you can also just create the dialog to show it later
ratingBuilder.create()
or you can show it immediately:
ratingBuilder.showNow()
Between the constructor and the show or create method you can adjust the dialog to suit your preferences. You have the following options:
If you want to use the in-app review from Google instead of the library dialog, call the following function:
.useGoogleInAppReview()
You can also add a completeListener
which gets called if the in-app review flow has been completed. The boolean indicates if the flow was started correctly, but not if the in-app review was displayed to the user.
.setGoogleInAppReviewCompleteListener(googleInAppReviewCompleteListener: (Boolean) -> Unit)
Note: After the first in-app review flow was completed successfully the toShowAgain
conditions will be used. For example .setMinimumLaunchTimesToShowAgain(launchTimesToShowAgain: Int)
instead of .setMinimumLaunchTimes(launchTimes: Int)
.
Testing the Google in-app review isn't as easy as it should be. There is an open issue in the issuetracker of Google: https://issuetracker.google.com/issues/167352813
Follow these tips on stackoverflow to maximize your chance of testing it successfully:
- Use only one account in the device
- Ensure that account has installed the app (appears in the app & games > Library section in Play Store)
- The account is a GMAIL one, not a GSuit
- You can review with the account if you go to the app play listing page.
- The account has not reviewed
- If you intend to use the Internal Test Track ensure the account has joined the test track.
- When switching between different accounts and testing things out, sometimes might be helpful to "Clear Data" from the Play Store app.
- Try all the above with different account
Source: https://stackoverflow.com/a/63950373
.setMinimumDays(minimumDays: Int) // default is 3
.setMinimumLaunchTimes(launchTimes: Int) // default is 5
later
button click.setMinimumDaysToShowAgain(minimumDaysToShowAgain: Int) // default is 14
later
button click.setMinimumLaunchTimesToShowAgain(launchTimesToShowAgain: Int) // default is 5
.setCustomCondition(customCondition: () -> Boolean)
later
button has been clicked. See below for more information..setCustomConditionToShowAgain(customConditionToShowAgain: () -> Boolean)
.dontCountThisAsAppLaunch()
The following settings will only take effect if the library dialog is used (and not the Google in-app review).
.setIconDrawable(iconDrawable: Drawable?) // default is null which means app icon
.setCustomTheme(customTheme: Int)
.setRateLaterButtonTextId(rateLaterButtonTextId: Int)
.setRateLaterButtonClickListener(rateLaterButtonClickListener: RateDialogClickListener)
.showRateNeverButton(rateNeverButtonTextId: Int, rateNeverButtonClickListener: RateDialogClickListener) // by default the button is hidden
.showRateNeverButtonAfterNTimes(rateNeverButtonTextId: Int, rateNeverButtonClickListener: RateDialogClickListener, countOfLaterButtonClicks: Int)
.setTitleTextId(titleTextId: Int)
.setMessageTextId(messageTextId: Int) // by default no message is shown
.setConfirmButtonTextId(confirmButtonTextId: Int)
.setConfirmButtonClickListener(confirmButtonClickListener: ConfirmButtonClickListener)
.setShowOnlyFullStars(showOnlyFullStars: Boolean) // default is false
.setStoreRatingTitleTextId(storeRatingTitleTextId: Int)
.setStoreRatingMessageTextId(storeRatingMessageTextId: Int)
.setRateNowButtonTextId(rateNowButtonTextId: Int)
.overwriteRateNowButtonClickListener(rateNowButtonClickListener: RateDialogClickListener) // by default it opens the Play Store listing of your app
.setAdditionalRateNowButtonClickListener(additionalRateNowButtonClickListener: RateDialogClickListener)
.setFeedbackTitleTextId(feedbackTitleTextId: Int)
.setNoFeedbackButtonTextId(noFeedbackButtonTextId: Int)
.setNoFeedbackButtonClickListener(noFeedbackButtonClickListener: RateDialogClickListener)
.setUseCustomFeedback(useCustomFeedback: Boolean) // default is false
If custom feedback is enabled, these settings will be ignored:
.setMailFeedbackMessageTextId(feedbackMailMessageTextId: Int)
.setMailSettingsForFeedbackDialog(mailSettings: MailSettings)
.setMailFeedbackButtonTextId(mailFeedbackButtonTextId: Int)
.overwriteMailFeedbackButtonClickListener(mailFeedbackButtonClickListener: RateDialogClickListener)
.setAdditionalMailFeedbackButtonClickListener(additionalMailFeedbackButtonClickListener: RateDialogClickListener)
These settings will only apply if custom feedback is enabled:
.setCustomFeedbackMessageTextId(feedbackCustomMessageTextId: Int)
.setCustomFeedbackButtonTextId(customFeedbackButtonTextId: Int)
.setCustomFeedbackButtonClickListener(customFeedbackButtonClickListener: CustomFeedbackButtonClickListener)
.setRatingThreshold(ratingThreshold: RatingThreshold) // default is RatingThreshold.THREE
later
button..setCancelable(cancelable: Boolean) // default is false
.setDialogCancelListener(dialogCancelListener: () -> Unit)
.setLoggingEnabled(isLoggingEnabled: Boolean) // default is true
showIfMeetsConditions()
(no conditions will be checked).setDebug(isDebug: Boolean) // default is false
AppRating.openMailFeedback(context: Context, mailSettings: MailSettings)
AppRating.openPlayStoreListing(context: Context)
AppRating.isDialogAgreed(context: Context)
AppRating.wasLaterButtonClicked(context: Context)
AppRating.wasNeverButtonClicked(context: Context)
AppRating.getNumberOfLaterButtonClicks(context: Context)
AppRating.reset(context: Context)
If the orientation is changed, the onCreate()
method will be called again and so does the Builder. These additional calls will distort the library behavior because each call of showIfMeetsConditions()
will increase the counted app launches. To guarantee the correct behavior, you have to check for the savedInstanceState
like this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
AppRating.Builder(this)
// your configuration
.showIfMeetsConditions()
}
}
You can easily use custom conditions to show the dialog not (only) on app start but e.g. directly after the nth user interaction. Just call the Builder with your conditions and dontCountThisAsAppLaunch()
:
AppRating.Builder(this)
// your other settings
.setCustomCondition { buttonClicks > 10 }
.setCustomConditionToShowAgain { buttonClicks > 20 }
.dontCountThisAsAppLaunch()
.showIfMeetsConditions()
If you want to show the dialog on app start, but with your custom conditions, you can of course just call the Builder in your onCreate()
method of your main Activity class. If so, don't forget to remove the dontCountThisAsAppLaunch()
method from the example above.
The libraries dialog is implemented as a DialogFragment
and thus needs a FragmentActivity
to get displayed. If you use Jetpack Compose your activity maybe extends from ComponentActivity
and because this class isn't a subtype of FragmentActivity
the dialog won't show up. You'll only see an error message in LogCat.
To get it working you just have to change your activity to extend from AppCompatActivity
instead (or FragmentActivity
). Or you just use the official Google in-app review which doesn't depend on fragments.
toShowAgain
conditions will be used. For example .setMinimumLaunchTimesToShowAgain(launchTimesToShowAgain: Int)
instead of .setMinimumLaunchTimes(launchTimes: Int)
setRatingThreshold(RatingThreshold.NONE)
if you don't want to show the feedback form to the usersetUseCustomFeedback()
to true
, you have to handle the feedback text by yourself by adding a click listener (setCustomFeedbackButtonClickListener()
)AppRating.Builder(this).showIfMeetsConditions()
without any settingsshowIfMeetsConditions()
and dontCountThisAsAppLaunch()
hasn't been calledawesome_app_rating
)The following things are highly recommended to not annoy the user, which in turn could lead to negative reviews:
Never
button (after n times) so the user can decide whether or not to rate your appopenPlayStoreListing()
and openMailFeedback()
in your app settings to give the user the ability of unprompted feedbackAppRating.reset(this)
in your production appCopyright (C) 2023 SuddenH4X
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.