Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT/#212] 인앱 업데이트를 구현합니다. #214

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.sopt.clody.data.local.repository

import com.google.android.play.core.appupdate.AppUpdateInfo

interface AppUpdateRepository {
fun checkForUpdate(callback: (AppUpdateInfo?) -> Unit)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.sopt.clody.data.local.repositoryimpl

import com.google.android.gms.tasks.Task
import com.google.android.play.core.appupdate.AppUpdateInfo
import com.google.android.play.core.appupdate.AppUpdateManager
import com.sopt.clody.data.local.repository.AppUpdateRepository
import javax.inject.Inject

class AppUpdateRepositoryImpl @Inject constructor
(private val appUpdateManager: AppUpdateManager) : AppUpdateRepository {
override fun checkForUpdate(callback: (AppUpdateInfo?) -> Unit) {
val appUpdateInfoTask: Task<AppUpdateInfo> = appUpdateManager.appUpdateInfo
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
callback(appUpdateInfo)
}.addOnFailureListener {
callback(null)
}
}
}
24 changes: 24 additions & 0 deletions app/src/main/java/com/sopt/clody/di/AppUpdateModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.sopt.clody.di

import android.content.Context
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AppUpdateModule {

@Provides
@Singleton
fun provideAppUpdateManager(
@ApplicationContext context: Context
): AppUpdateManager {
return AppUpdateManagerFactory.create(context)
}
}
8 changes: 8 additions & 0 deletions app/src/main/java/com/sopt/clody/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.sopt.clody.di

import com.sopt.clody.data.local.repository.AppUpdateRepository
import com.sopt.clody.data.local.repositoryimpl.AppUpdateRepositoryImpl
import com.sopt.clody.data.repository.AccountManagementRepository
import com.sopt.clody.data.repository.AuthRepository
import com.sopt.clody.data.repository.DailyDiariesRepository
Expand Down Expand Up @@ -106,4 +108,10 @@ abstract class RepositoryModule {
abstract fun bindNotificationRepository(
notificationRepositoryImpl: NotificationRepositoryImpl
): NotificationRepository

@Binds
@Singleton
abstract fun bindAppUpdateRepository(
appUpdateRepositoryImpl: AppUpdateRepositoryImpl
): AppUpdateRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.sopt.clody.presentation.ui.main

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.android.play.core.appupdate.AppUpdateInfo
import com.sopt.clody.data.local.repository.AppUpdateRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class AppUpdateViewModel @Inject constructor(
private val appUpdateRepository: AppUpdateRepository
) : ViewModel() {

private val _appUpdateInfo = MutableSharedFlow<AppUpdateInfo?>()
val appUpdateInfo: SharedFlow<AppUpdateInfo?> = _appUpdateInfo.asSharedFlow()

fun checkForAppUpdate() {
viewModelScope.launch {
appUpdateRepository.checkForUpdate { updateInfo ->
viewModelScope.launch {
_appUpdateInfo.emit(updateInfo)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@ package com.sopt.clody.presentation.ui.main
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.compose.rememberNavController
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateOptions
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.UpdateAvailability
import com.sopt.clody.presentation.ui.auth.navigation.AuthNavigator
import com.sopt.clody.presentation.ui.diarylist.navigation.DiaryListNavigator
import com.sopt.clody.presentation.ui.home.navigation.HomeNavigator
Expand All @@ -20,12 +28,20 @@ import com.sopt.clody.presentation.ui.setting.navigation.SettingNavigator
import com.sopt.clody.presentation.ui.writediary.navigation.WriteDiaryNavigator
import com.sopt.clody.ui.theme.CLODYTheme
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

@Inject
lateinit var appUpdateManager: AppUpdateManager
private val appUpdateViewModel: AppUpdateViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
checkForAppUpdate()
setContent {
CLODYTheme {
val navController = rememberNavController()
Expand Down Expand Up @@ -63,4 +79,47 @@ class MainActivity : ComponentActivity() {
}
}
}

private fun checkForAppUpdate() {
appUpdateViewModel.checkForAppUpdate()

lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
appUpdateViewModel.appUpdateInfo.collect { appUpdateInfo ->
appUpdateInfo?.let {
if (it.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE &&
it.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
) {

val appUpdateOptions = AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build()
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
this@MainActivity,
appUpdateOptions,
REQUEST_CODE_UPDATE
)
}
}
}
}
}
}

override fun onResume() {
super.onResume()
appUpdateManager.appUpdateInfo.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
val appUpdateOptions = AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build()
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
this,
appUpdateOptions,
REQUEST_CODE_UPDATE
)
}
}
}
companion object {
const val REQUEST_CODE_UPDATE = 100
}
}