Skip to content

Instantly share code, notes, and snippets.

@JakeSteam
Last active November 9, 2024 22:42
Show Gist options
  • Save JakeSteam/437b1085b9639061955157776911697a to your computer and use it in GitHub Desktop.
Save JakeSteam/437b1085b9639061955157776911697a to your computer and use it in GitHub Desktop.
Forcing app updates on Android using Google's in-app update library https://blog.jakelee.co.uk/implementing-google-in-app-updates-for-android/
dependencies {
implementation(libs.android.playAppUpdate)
implementation(libs.android.playAppUpdateKtx)
}
// Adapted from https://developer.android.com/guide/playcore/in-app-updates/kotlin-java
class ForceUpdateHandler @Inject constructor(
private val abTestManager: ABTestManager // Optional
) {
fun forceUpdateIfNeeded(activity: ComponentActivity) {
// Optional, an optimisation / safety check
val minimumAllowedVersion = abTestManager.remoteConfigLong(FirebaseRemoteConfigKeys.minimum_version)
if (BuildConfig.VERSION_CODE >= minimumAllowedVersion) {
return
}
// Must be declared before activity is resumed: https://stackoverflow.com/a/67582633/608312
val activityResult = activity.registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
handleUpdateResult(result) {
activity.finish()
}
}
val appUpdateManager = AppUpdateManagerFactory.create(activity)
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
appUpdateInfoTask.addOnSuccessListener { updateInfo ->
if (updateInfo.isUpdateInProgress() || updateInfo.isForceUpdateRequired()) {
startForceUpdateFlow(updateInfo, activityResult, appUpdateManager)
}
}
}
private fun AppUpdateInfo.isUpdateInProgress() =
updateAvailability() == DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS
private fun AppUpdateInfo.isForceUpdateRequired() =
updateAvailability() == UPDATE_AVAILABLE && isUpdateTypeAllowed(IMMEDIATE)
private fun startForceUpdateFlow(
appUpdateInfo: AppUpdateInfo,
activityResultLauncher: ActivityResultLauncher<IntentSenderRequest>,
appUpdateManager: AppUpdateManager
) {
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
activityResultLauncher,
AppUpdateOptions.newBuilder(IMMEDIATE).build()
)
}
private fun handleUpdateResult(result: ActivityResult, onUpdateDialogClose: () -> Unit) {
when (result.resultCode) {
Activity.RESULT_OK -> Timber.i("User has started mandatory update")
Activity.RESULT_CANCELED -> onUpdateDialogClose.invoke()
RESULT_IN_APP_UPDATE_FAILED -> Timber.i("Mandatory update failed")
else -> Timber.i("Error whilst updating (${result.resultCode}): ${result.data?.data}")
}
}
}
[versions]
android-playAppUpdate = '2.1.0'
[libraries]
android-playAppUpdate = { module = "com.google.android.play:app-update", version.ref = "android-playAppUpdate" }
android-playAppUpdateKtx = { module = "com.google.android.play:app-update-ktx", version.ref = "android-playAppUpdate" }
updateHandler.forceUpdateIfNeeded(this)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment