Last active
January 9, 2025 11:28
-
-
Save JakeSteam/c09c7bd980095a8a26649419d49d393e to your computer and use it in GitHub Desktop.
Remotely configurable in-app Play Store review prompt in Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MyFragment { | |
val navToBookings: () -> Unit = { | |
findNavController().navigate(MyFragmentDirections.toBookings()) | |
} | |
fun eventHandler(event: TicketConfirmationEvents) { | |
when (event) { | |
is TicketConfirmationEvents.OnLookAtMyTicket -> { | |
viewModel.onLookAtMyTicket(navToBookings) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MyViewModel( | |
reviewPromptHandler: ReviewPromptHandler | |
) { | |
init { | |
reviewPromptHandler.prepareReviewPrompt(ReviewPromptTrigger.TICKET_PURCHASED) | |
} | |
fun onLookAtMyTicket(navigation: () -> Unit) { | |
reviewPromptHandler.showReviewPrompt(ReviewPromptTrigger.TICKET_PURCHASED, navigation) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Singleton | |
class ReviewPromptHandler @Inject constructor( | |
application: Application, | |
private val remoteConfigManager: RemoteConfigManager | |
) { | |
private val reviewManager = ReviewManagerFactory.create(application) | |
private var activity: Activity? = null | |
internal var preparedReviewPrompt: ReviewInfo? = null | |
private val triggersThisSession = mutableListOf<ReviewPromptTrigger>() | |
fun setActivity(activity: Activity) { | |
this.activity = activity | |
} | |
fun prepareReviewPrompt(trigger: ReviewPromptTrigger) { | |
preparedReviewPrompt = null | |
if (!shouldShow(trigger)) { | |
return | |
} | |
reviewManager.requestReviewFlow().addOnCompleteListener { request -> | |
if (request.isSuccessful) { | |
preparedReviewPrompt = request.result | |
} | |
} | |
} | |
fun showReviewPrompt(trigger: ReviewPromptTrigger, callback: () -> Unit = {}) { | |
val activity = activity | |
if (!shouldShow(trigger) || activity == null) { | |
callback() | |
return | |
} | |
triggersThisSession.add(trigger) | |
preparedReviewPrompt?.let { | |
launchReviewPrompt(activity, it, callback) | |
} ?: prepareAndLaunchReviewPrompt(activity, callback) | |
} | |
private fun shouldShow(trigger: ReviewPromptTrigger): Boolean { | |
if (triggersThisSession.contains(trigger)) { | |
return false | |
} | |
return remoteConfigManager.getString(review_prompt_triggers) | |
.split(",") | |
.map { it.trim() } | |
.contains(trigger.remoteName) | |
} | |
private fun prepareAndLaunchReviewPrompt(activity: Activity, callback: () -> Unit) { | |
reviewManager.requestReviewFlow().addOnCompleteListener { request -> | |
if (request.isSuccessful) { | |
launchReviewPrompt(activity, request.result, callback) | |
} else { | |
Log.i("ReviewPromptHandler", "Failed to prepareAndLaunchReviewPrompt") | |
callback() | |
} | |
} | |
} | |
private fun launchReviewPrompt(activity: Activity, reviewInfo: ReviewInfo, callback: () -> Unit) { | |
reviewManager.launchReviewFlow(activity, reviewInfo).addOnCompleteListener { | |
if (!it.isSuccessful) { | |
Log.i("ReviewPromptHandler", "Failed to launchReviewPrompt") | |
} | |
callback() | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://developer.android.com/guide/playcore/in-app-review#when-to-request | |
enum class ReviewPromptTrigger(val remoteName: String) { | |
BID_MADE("BID_MADE"), | |
BUN_PURCHASED("BUN_PURCHASED"), | |
TICKET_PURCHASED("TICKET_PURCHASED") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment