diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0036a99dd..50fa69f17 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -226,6 +226,8 @@ dependencies { implementation(libs.androidx.lifecycle.livedata.ktx) implementation(libs.play.services.base) + implementation(libs.app.update) + implementation(libs.app.update.ktx) // Firebase implementation(platform(libs.firebase.bom)) diff --git a/app/src/main/java/com/eatssu/android/presentation/MainActivity.kt b/app/src/main/java/com/eatssu/android/presentation/MainActivity.kt index a007b5a29..2be64df94 100644 --- a/app/src/main/java/com/eatssu/android/presentation/MainActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/MainActivity.kt @@ -1,5 +1,6 @@ package com.eatssu.android.presentation + import android.Manifest import android.annotation.SuppressLint import android.content.pm.PackageManager @@ -47,6 +48,7 @@ class MainActivity : BaseActivity( private val mainViewModel: MainViewModel by viewModels() private val myPageViewModel: MyPageViewModel by viewModels() + @SuppressLint("SuspiciousIndentation") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -54,40 +56,13 @@ class MainActivity : BaseActivity( setupNoToolbar() setNavigation() + checkAlarmPermission() collectState() collectUiEvents() } - private fun setNavigation() { - val navHostFragment = supportFragmentManager - .findFragmentById(R.id.nav_host_fragment) as NavHostFragment - val navController = navHostFragment.navController - binding.bottomNaviBar.itemIconTintList = null - - binding.bottomNaviBar.setOnSingleItemSelectedListener { item -> - when (item.itemId) { - R.id.cafeteria_menu -> { - navController.navigate(R.id.cafeteria_menu) - true - } - R.id.map_menu -> { - navController.navigate(R.id.mapFragment) - true - } - - R.id.mypage_menu -> { - navController.navigate(R.id.myPageFragment) - true - } - - else -> { - false - } - } - } - } // set UI -- private fun setupNoToolbar() { @@ -198,5 +173,35 @@ class MainActivity : BaseActivity( } + private fun setNavigation() { + val navHostFragment = supportFragmentManager + .findFragmentById(R.id.nav_host_fragment) as NavHostFragment + val navController = navHostFragment.navController + binding.bottomNaviBar.itemIconTintList = null + + binding.bottomNaviBar.setOnSingleItemSelectedListener { item -> + when (item.itemId) { + R.id.cafeteria_menu -> { + navController.navigate(R.id.cafeteria_menu) + true + } + + R.id.map_menu -> { + navController.navigate(R.id.mapFragment) + true + } + + R.id.mypage_menu -> { + navController.navigate(R.id.myPageFragment) + true + } + + else -> { + false + } + } + } + } + override fun shouldLogScreenId() = false } \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/intro/IntroActivity.kt b/app/src/main/java/com/eatssu/android/presentation/intro/IntroActivity.kt index 35cd4af3b..78880a271 100644 --- a/app/src/main/java/com/eatssu/android/presentation/intro/IntroActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/intro/IntroActivity.kt @@ -6,6 +6,7 @@ import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope +import com.eatssu.android.R import com.eatssu.android.databinding.ActivityIntroBinding import com.eatssu.android.presentation.MainActivity import com.eatssu.android.presentation.common.ForceUpdateDialogActivity @@ -16,8 +17,15 @@ import com.eatssu.android.presentation.util.startActivity import com.eatssu.common.EventLogger import com.eatssu.common.UiEvent import com.eatssu.common.UiState +import com.eatssu.common.UiText + import com.eatssu.common.enums.LaunchPath import com.eatssu.common.enums.ScreenId +import com.eatssu.common.enums.ToastType +import com.google.android.play.core.appupdate.AppUpdateManager +import com.google.android.play.core.appupdate.AppUpdateManagerFactory +import com.google.android.play.core.install.model.AppUpdateType +import com.google.android.play.core.install.model.UpdateAvailability import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -27,6 +35,8 @@ class IntroActivity : AppCompatActivity() { private val introViewModel: IntroViewModel by viewModels() private lateinit var binding: ActivityIntroBinding + private lateinit var appUpdateManager: AppUpdateManager + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -35,6 +45,8 @@ class IntroActivity : AppCompatActivity() { setContentView(binding.root) log() + checkAppUpdate() + observeState() observeEvents() observeNetworkError() @@ -105,10 +117,68 @@ class IntroActivity : AppCompatActivity() { override fun onResume() { super.onResume() EventLogger.screenView(ScreenId.LOGIN_SPLASH) + + if (::appUpdateManager.isInitialized) { + appUpdateManager.appUpdateInfo.addOnSuccessListener { appUpdateInfo -> + if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) { + // If an in-app update is already in progress, resume the update. + appUpdateManager.startUpdateFlowForResult( + appUpdateInfo, + AppUpdateType.IMMEDIATE, + this, + UPDATE_REQUEST_CODE + ) + } + } + } } private fun showForceUpdateDialog() { val intent = Intent(this, ForceUpdateDialogActivity::class.java) startActivity(intent) } + + private fun checkAppUpdate() { + appUpdateManager = AppUpdateManagerFactory.create(this) + + val appUpdateInfoTask = appUpdateManager.appUpdateInfo + + appUpdateInfoTask.addOnSuccessListener { appUpdateInfo -> + if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && + appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) + ) { + appUpdateManager.startUpdateFlowForResult( + appUpdateInfo, + AppUpdateType.IMMEDIATE, + this, + UPDATE_REQUEST_CODE + ) + } else { + introViewModel.startAppChecks() + } + }.addOnFailureListener { + introViewModel.startAppChecks() + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + + if (requestCode == UPDATE_REQUEST_CODE) { + if (resultCode != RESULT_OK) { + showToast( + UiEvent.ShowToast( + UiText.StringResource(R.string.toast_app_update_canceled), ToastType.INFO + ) + ) + // If the update is cancelled or fails, + // you can request to start the update again. + introViewModel.startAppChecks() + } + } + } + + companion object { + const val UPDATE_REQUEST_CODE = 500 + } } \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/intro/IntroViewModel.kt b/app/src/main/java/com/eatssu/android/presentation/intro/IntroViewModel.kt index 5ff083ed7..87a825b50 100644 --- a/app/src/main/java/com/eatssu/android/presentation/intro/IntroViewModel.kt +++ b/app/src/main/java/com/eatssu/android/presentation/intro/IntroViewModel.kt @@ -37,11 +37,11 @@ class IntroViewModel @Inject constructor( private val _versionCheckResult = MutableStateFlow(null) val versionCheckResult: StateFlow = _versionCheckResult.asStateFlow() - init { - initializeApp() - } + // init { + // initializeApp() + // } - private fun initializeApp() { + fun startAppChecks() { viewModelScope.launch { _uiState.value = UiState.Loading diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 49293065c..b13c7b830 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -118,6 +118,7 @@ 앱 초기화 중 오류가 발생했습니다 앱을 업데이트해주세요 + 업데이트가 취소되었어요 제휴 정보가 없습니다. 로그인에 실패했어요. 로그아웃했어요. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8077dd9bf..1d974e2ab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -62,6 +62,7 @@ glanceAppwidgetPreview = "1.1.1" glancePreview = "1.1.1" posthog = "3.+" paging = "3.3.6" +app-update = "2.1.0" [libraries] @@ -141,6 +142,8 @@ firebase-config = { group = "com.google.firebase", name = "firebase-config" } firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics" } firebase-messaging = { group = "com.google.firebase", name = "firebase-messaging" } play-services-base = { group = "com.google.android.gms", name = "play-services-base", version.ref = "play-services-base" } +app-update = { group = "com.google.android.play", name = "app-update", version.ref = "app-update" } +app-update-ktx = { group = "com.google.android.play", name = "app-update-ktx", version.ref = "app-update" } # etc accompanist-appcompat-theme = { group = "com.google.accompanist", name = "accompanist-appcompat-theme", version.ref = "accompanistAppcompatTheme" }