From a992c40c1da0b443a5e3f422eba9c39ec370743e Mon Sep 17 00:00:00 2001 From: kkosang Date: Wed, 9 Oct 2024 15:21:44 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20In-App=20update=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle.kts | 2 ++ android/gradle/libs.versions.toml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index b726e91e1..8a7234ee8 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -200,6 +200,8 @@ dependencies { implementation(platform(libs.firebase.bom)) implementation(libs.firebase.crashlytics.buildtools) implementation(libs.bundles.firebase) + implementation(libs.app.update) + implementation(libs.app.update.ktx) // android test androidTestImplementation(libs.bundles.android.test) androidTestRuntimeOnly(libs.junit5.android.test.runner) diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 91fe7289d..dd647aec2 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -37,6 +37,7 @@ datastore = "1.0.0" google-services = "4.4.2" firebase = "33.1.2" firebase-crashlytics = "3.0.2" +app-update = "2.1.0" # Android-Test android-junit5-plugin = "1.10.0.0" @@ -89,6 +90,8 @@ firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "fir firebase-analytics = { module = "com.google.firebase:firebase-analytics-ktx" } firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx" } firebase-crashlytics-plugin = { module = "com.google.firebase:firebase-crashlytics-gradle", version.ref = "firebase-crashlytics" } +app-update = { module = "com.google.android.play:app-update", version.ref = "app-update" } +app-update-ktx = { module = "com.google.android.play:app-update-ktx", version.ref = "app-update" } # android test androidx-test-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-test-junit" } android-test-fragment = { module = "androidx.fragment:fragment-testing", version.ref = "androidx-test-fragment" } From 27b58b35254347b228378d6d22a23ae87e022efa Mon Sep 17 00:00:00 2001 From: kkosang Date: Fri, 11 Oct 2024 16:14:28 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EC=9D=B8=EC=95=B1=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../helper/presentation/home/HomeActivity.kt | 27 ++++++++ .../poke/rogue/helper/update/UpdateManager.kt | 65 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 android/app/src/main/java/poke/rogue/helper/update/UpdateManager.kt diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/home/HomeActivity.kt b/android/app/src/main/java/poke/rogue/helper/presentation/home/HomeActivity.kt index 16f08b0c7..8b57e28a6 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/home/HomeActivity.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/home/HomeActivity.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle +import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import androidx.appcompat.widget.Toolbar import poke.rogue.helper.R @@ -22,20 +23,46 @@ import poke.rogue.helper.presentation.util.context.stringOf import poke.rogue.helper.presentation.util.context.toast import poke.rogue.helper.presentation.util.logClickEvent import poke.rogue.helper.presentation.util.repeatOnStarted +import poke.rogue.helper.update.UpdateManager +import timber.log.Timber class HomeActivity : ToolbarActivity(R.layout.activity_home) { private val viewModel by viewModels() private val logger: AnalyticsLogger = analyticsLogger() + private lateinit var updateManager: UpdateManager override val toolbar: Toolbar get() = binding.toolbarHome override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + initUpdateManager() initViews() initObservers() } + override fun onDestroy() { + super.onDestroy() + updateManager.unregisterInstallStateUpdateListener() + } + + private fun initUpdateManager() { + updateManager = UpdateManager(applicationContext) + updateManager.registerInstallStateUpdateListener() + + val appUpdateLauncher = registerForActivityResult( + ActivityResultContracts.StartIntentSenderForResult() + ) { result -> + // logger도 달아야겠죠?? + if (result.resultCode == RESULT_OK) { + Timber.i("Update completed successfully") + } else { + Timber.e("Update failed, result code: ${result.resultCode}") + } + } + updateManager.checkForAppUpdates(appUpdateLauncher) + } + private fun initViews() = with(binding) { supportActionBar?.setDisplayShowTitleEnabled(false) diff --git a/android/app/src/main/java/poke/rogue/helper/update/UpdateManager.kt b/android/app/src/main/java/poke/rogue/helper/update/UpdateManager.kt new file mode 100644 index 000000000..9dceff655 --- /dev/null +++ b/android/app/src/main/java/poke/rogue/helper/update/UpdateManager.kt @@ -0,0 +1,65 @@ +package poke.rogue.helper.update + +import android.content.Context +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.IntentSenderRequest +import com.google.android.play.core.appupdate.AppUpdateInfo +import com.google.android.play.core.appupdate.AppUpdateManager +import com.google.android.play.core.appupdate.AppUpdateManagerFactory +import com.google.android.play.core.appupdate.AppUpdateOptions +import com.google.android.play.core.install.InstallStateUpdatedListener +import com.google.android.play.core.install.model.AppUpdateType +import com.google.android.play.core.install.model.InstallStatus +import com.google.android.play.core.install.model.UpdateAvailability +import timber.log.Timber + + +class UpdateManager( + private val context: Context +) { + private val appUpdateManager: AppUpdateManager = AppUpdateManagerFactory.create(context) + private val updateType = AppUpdateType.FLEXIBLE + + private val installStateUpdateListener = InstallStateUpdatedListener { state -> + when (state.installStatus()) { + InstallStatus.INSTALLING -> Timber.i("Update is downloading") + + InstallStatus.DOWNLOADED -> { + Timber.i("Update installed successfully") + appUpdateManager.completeUpdate() + } + + InstallStatus.CANCELED -> Timber.e("Update was cancelled") + } + } + + fun checkForAppUpdates( + appUpdateLauncher: ActivityResultLauncher + ) { + appUpdateManager.appUpdateInfo.addOnSuccessListener { info -> + if (checkForAppUpdate(info)) { + val updateOptions = AppUpdateOptions.newBuilder(updateType).build() + appUpdateManager.startUpdateFlowForResult( + info, + appUpdateLauncher, + updateOptions + ) + } + } + } + + private fun checkForAppUpdate(info: AppUpdateInfo): Boolean { + val isUpdateAvailable = info.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE + val isUpdateAllowed = info.isUpdateTypeAllowed(updateType) + return isUpdateAvailable && isUpdateAllowed + } + + + fun registerInstallStateUpdateListener() { + appUpdateManager.registerListener(installStateUpdateListener) + } + + fun unregisterInstallStateUpdateListener() { + appUpdateManager.unregisterListener(installStateUpdateListener) + } +} From ec0dee8aff8a9d711b114832e2115a249516b9b1 Mon Sep 17 00:00:00 2001 From: kkosang Date: Fri, 11 Oct 2024 16:15:14 +0900 Subject: [PATCH 3/3] style: ktFormat --- .../helper/presentation/home/HomeActivity.kt | 19 ++++++------ .../poke/rogue/helper/update/UpdateManager.kt | 29 +++++++++---------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/home/HomeActivity.kt b/android/app/src/main/java/poke/rogue/helper/presentation/home/HomeActivity.kt index 8b57e28a6..9c2c7151f 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/home/HomeActivity.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/home/HomeActivity.kt @@ -50,16 +50,17 @@ class HomeActivity : ToolbarActivity(R.layout.activity_home updateManager = UpdateManager(applicationContext) updateManager.registerInstallStateUpdateListener() - val appUpdateLauncher = registerForActivityResult( - ActivityResultContracts.StartIntentSenderForResult() - ) { result -> - // logger도 달아야겠죠?? - if (result.resultCode == RESULT_OK) { - Timber.i("Update completed successfully") - } else { - Timber.e("Update failed, result code: ${result.resultCode}") + val appUpdateLauncher = + registerForActivityResult( + ActivityResultContracts.StartIntentSenderForResult(), + ) { result -> + // logger도 달아야겠죠?? + if (result.resultCode == RESULT_OK) { + Timber.i("Update completed successfully") + } else { + Timber.e("Update failed, result code: ${result.resultCode}") + } } - } updateManager.checkForAppUpdates(appUpdateLauncher) } diff --git a/android/app/src/main/java/poke/rogue/helper/update/UpdateManager.kt b/android/app/src/main/java/poke/rogue/helper/update/UpdateManager.kt index 9dceff655..cc0eca2ef 100644 --- a/android/app/src/main/java/poke/rogue/helper/update/UpdateManager.kt +++ b/android/app/src/main/java/poke/rogue/helper/update/UpdateManager.kt @@ -13,36 +13,34 @@ import com.google.android.play.core.install.model.InstallStatus import com.google.android.play.core.install.model.UpdateAvailability import timber.log.Timber - class UpdateManager( - private val context: Context + private val context: Context, ) { private val appUpdateManager: AppUpdateManager = AppUpdateManagerFactory.create(context) private val updateType = AppUpdateType.FLEXIBLE - private val installStateUpdateListener = InstallStateUpdatedListener { state -> - when (state.installStatus()) { - InstallStatus.INSTALLING -> Timber.i("Update is downloading") + private val installStateUpdateListener = + InstallStateUpdatedListener { state -> + when (state.installStatus()) { + InstallStatus.INSTALLING -> Timber.i("Update is downloading") - InstallStatus.DOWNLOADED -> { - Timber.i("Update installed successfully") - appUpdateManager.completeUpdate() - } + InstallStatus.DOWNLOADED -> { + Timber.i("Update installed successfully") + appUpdateManager.completeUpdate() + } - InstallStatus.CANCELED -> Timber.e("Update was cancelled") + InstallStatus.CANCELED -> Timber.e("Update was cancelled") + } } - } - fun checkForAppUpdates( - appUpdateLauncher: ActivityResultLauncher - ) { + fun checkForAppUpdates(appUpdateLauncher: ActivityResultLauncher) { appUpdateManager.appUpdateInfo.addOnSuccessListener { info -> if (checkForAppUpdate(info)) { val updateOptions = AppUpdateOptions.newBuilder(updateType).build() appUpdateManager.startUpdateFlowForResult( info, appUpdateLauncher, - updateOptions + updateOptions, ) } } @@ -54,7 +52,6 @@ class UpdateManager( return isUpdateAvailable && isUpdateAllowed } - fun registerInstallStateUpdateListener() { appUpdateManager.registerListener(installStateUpdateListener) }