diff --git a/app/src/play/java/io/github/wulkanowy/utils/UpdateHelper.kt b/app/src/play/java/io/github/wulkanowy/utils/UpdateHelper.kt index 7586a21a..1dd3bc68 100644 --- a/app/src/play/java/io/github/wulkanowy/utils/UpdateHelper.kt +++ b/app/src/play/java/io/github/wulkanowy/utils/UpdateHelper.kt @@ -17,6 +17,7 @@ import com.google.android.play.core.install.model.UpdateAvailability.DEVELOPER_T import com.google.android.play.core.install.model.UpdateAvailability.UPDATE_AVAILABLE import com.google.android.play.core.ktx.isFlexibleUpdateAllowed import com.google.android.play.core.ktx.isImmediateUpdateAllowed +import com.google.android.play.core.ktx.updatePriority import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.R import timber.log.Timber @@ -24,40 +25,57 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class UpdateHelper @Inject constructor(@ApplicationContext private val context: Context) { +class UpdateHelper @Inject constructor( + @ApplicationContext private val context: Context, + private val analyticsHelper: AnalyticsHelper, +) { lateinit var messageContainer: View - companion object { - const val IN_APP_UPDATE_REQUEST_CODE = 1721 - - const val DAYS_FOR_FLEXIBLE_UPDATE = 7 - const val HIGH_PRIORITY_UPDATE = 4 - } - private val appUpdateManager by lazy { AppUpdateManagerFactory.create(context) } private val flexibleUpdateListener = InstallStateUpdatedListener { state -> when (state.installStatus()) { - PENDING -> Toast.makeText(context, R.string.update_download_started, Toast.LENGTH_SHORT).show() + PENDING -> Toast.makeText(context, R.string.update_download_started, Toast.LENGTH_SHORT) + .show() DOWNLOADED -> popupSnackBarForCompleteUpdate() else -> Timber.d("Update state: ${state.installStatus()}") } } private inline val AppUpdateInfo.isImmediateUpdateAvailable: Boolean - get() = updateAvailability() == UPDATE_AVAILABLE && isImmediateUpdateAllowed && - updatePriority() >= HIGH_PRIORITY_UPDATE + get() { + val days = clientVersionStalenessDays() ?: 0 + val isUpdatePriorityAllowUpdate = when (updatePriority) { + 5 -> true + 4 -> days > 7 + 3 -> days > 30 + else -> false + } + + return updateAvailability() == UPDATE_AVAILABLE && isImmediateUpdateAllowed && isUpdatePriorityAllowUpdate + } private inline val AppUpdateInfo.isFlexibleUpdateAvailable: Boolean - get() = updateAvailability() == UPDATE_AVAILABLE && isFlexibleUpdateAllowed && - clientVersionStalenessDays() ?: 0 >= DAYS_FOR_FLEXIBLE_UPDATE + get() { + val days = clientVersionStalenessDays() ?: 0 + val isUpdatePriorityAllowUpdate = when (updatePriority) { + 4, 3, 2 -> true + 1 -> days >= 7 + 0 -> false + else -> false + } + + return updateAvailability() == UPDATE_AVAILABLE && isFlexibleUpdateAllowed && isUpdatePriorityAllowUpdate + } fun checkAndInstallUpdates(activity: Activity) { Timber.d("Checking for updates...") appUpdateManager.appUpdateInfo.addOnSuccessListener { appUpdateInfo -> when { - appUpdateInfo.isImmediateUpdateAvailable -> startUpdate(activity, appUpdateInfo, IMMEDIATE) + appUpdateInfo.isImmediateUpdateAvailable -> { + startUpdate(activity, appUpdateInfo, IMMEDIATE) + } appUpdateInfo.isFlexibleUpdateAvailable -> { appUpdateManager.registerListener(flexibleUpdateListener) startUpdate(activity, appUpdateInfo, FLEXIBLE) @@ -68,15 +86,20 @@ class UpdateHelper @Inject constructor(@ApplicationContext private val context: } private fun startUpdate(activity: Activity, appUpdateInfo: AppUpdateInfo, updateType: Int) { + Timber.d("Start update ($updateType): $appUpdateInfo") appUpdateManager.startUpdateFlowForResult( appUpdateInfo, updateType, activity, IN_APP_UPDATE_REQUEST_CODE ) } fun onActivityResult(requestCode: Int, resultCode: Int) { - if (requestCode == IN_APP_UPDATE_REQUEST_CODE && resultCode != RESULT_OK) { - Timber.e("Update failed! Result code: $resultCode") - Toast.makeText(context, R.string.update_failed, Toast.LENGTH_LONG).show() + if (requestCode == IN_APP_UPDATE_REQUEST_CODE) { + if (resultCode != RESULT_OK) { + Timber.i("Update failed! Result code: $resultCode") + Toast.makeText(context, R.string.update_failed, Toast.LENGTH_LONG).show() + } + + analyticsHelper.logEvent("inapp_update", "code" to resultCode) } } @@ -87,14 +110,23 @@ class UpdateHelper @Inject constructor(@ApplicationContext private val context: when { DOWNLOADED == info.installStatus() -> popupSnackBarForCompleteUpdate() DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS == info.updateAvailability() -> { - startUpdate(activity, info, if (info.isImmediateUpdateAvailable) IMMEDIATE else FLEXIBLE) + startUpdate( + activity = activity, + appUpdateInfo = info, + updateType = if (info.isImmediateUpdateAvailable) IMMEDIATE else FLEXIBLE + ) } } } } private fun popupSnackBarForCompleteUpdate() { - Snackbar.make(messageContainer, R.string.update_download_success, Snackbar.LENGTH_INDEFINITE).apply { + Timber.d("Show snackbar with update complete") + Snackbar.make( + messageContainer, + R.string.update_download_success, + Snackbar.LENGTH_INDEFINITE + ).apply { setAction(R.string.update_download_success_button) { appUpdateManager.completeUpdate() appUpdateManager.unregisterListener(flexibleUpdateListener) @@ -102,4 +134,9 @@ class UpdateHelper @Inject constructor(@ApplicationContext private val context: show() } } + + private companion object { + + private const val IN_APP_UPDATE_REQUEST_CODE = 1721 + } }