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

RemoteConfig 이용해서 앱 업데이트 되도록 수정 #276

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 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
2 changes: 2 additions & 0 deletions app/src/main/java/team/ppac/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import dagger.hilt.android.AndroidEntryPoint
import team.ppac.analytics.AnalyticsHelper
import team.ppac.common.android.util.remoteConfigInit
import team.ppac.designsystem.FarmemeTheme
import team.ppac.designsystem.component.scaffold.FarmemeScaffold
import team.ppac.designsystem.component.scaffold.type.BackgroundColorType
Expand Down Expand Up @@ -38,6 +39,7 @@ class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
remoteConfigInit()
WindowCompat.setDecorFitsSystemWindows(window, false)
val memeId = AppsFlyerLibRequester.memeId

Expand Down
3 changes: 3 additions & 0 deletions core/common/android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ dependencies {
implementation(libs.app.update)
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.crashlytics)
implementation(libs.firebase.analytics)
implementation(libs.firebase.config.ktx)
implementation(libs.play.services.base)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package team.ppac.common.android.util

import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.widget.Toast
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.ktx.Firebase
import com.google.firebase.remoteconfig.ConfigUpdate
import com.google.firebase.remoteconfig.ConfigUpdateListener
import com.google.firebase.remoteconfig.FirebaseRemoteConfigException
import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
import team.ppac.common.android.R
import timber.log.Timber

const val REMOTE_KEY_APP_VERSION = "latest_version"
const val TAG = "RemoteConfig"
fun remoteConfigInit() {
val remoteConfig = Firebase.remoteConfig
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = 3600
}
remoteConfig.setConfigSettingsAsync(configSettings)

remoteConfig.fetchAndActivate().addOnCompleteListener { task ->
val latestVersion = remoteConfig.getString(REMOTE_KEY_APP_VERSION)
if (task.isSuccessful) {
Timber.tag(TAG).i("remoteConfigInit - Success= $latestVersion")
} else {
Timber.tag(TAG).i("remoteConfigInit - Fail= $latestVersion")
}
}

remoteConfig.addOnConfigUpdateListener(object : ConfigUpdateListener {
override fun onUpdate(configUpdate: ConfigUpdate) {
Timber.tag(TAG).d("Updated keys: ${configUpdate.updatedKeys}")
if (configUpdate.updatedKeys.contains(REMOTE_KEY_APP_VERSION)) {
remoteConfig.activate()
.addOnCompleteListener { task ->
val latestVersion = remoteConfig.getString(REMOTE_KEY_APP_VERSION)
if (task.isSuccessful) {
Timber.tag(TAG).i("remoteConfigInit update - Success= $latestVersion")
} else {
Timber.tag(TAG).i("remoteConfigInit update - Fail= $latestVersion")
}
}
}
}

override fun onError(error: FirebaseRemoteConfigException) {
Timber.tag(TAG).w(error, "Config update error with code: ${error.code}")
}
})
}

fun needToUpdateVersion(context: Context): Boolean {
val latestVersion = Firebase.remoteConfig.getString(REMOTE_KEY_APP_VERSION)
val currentAppVersion =
context.packageManager.getPackageInfoCompat(context.packageName).versionName
Timber.tag(TAG).i("needToUpdateVersion: currentAppVersion= $currentAppVersion")
return latestVersion.isNotEmpty() && latestVersion != currentAppVersion
}

fun launchGooglePlayStore(context: Context): Boolean {
if (checkGooglePlayServices(context)) {
val uri = "market://details?id=${context.packageName}"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(uri))
context.startActivity(intent)
return true
}
return false
}

private fun checkGooglePlayServices(context: Context): Boolean {
val googleApiAvailability = GoogleApiAvailability.getInstance()
val status = googleApiAvailability.isGooglePlayServicesAvailable(context)
if (status != ConnectionResult.SUCCESS) {
Timber.tag(TAG).w("구글 플레이 스토어 열기 실패")
Toast.makeText(
context,
context.getString(R.string.version_update_dialog_fail_toast),
Toast.LENGTH_SHORT
).show()
return false
}
return true
}

private fun PackageManager.getPackageInfoCompat(packageName: String, flags: Int = 0): PackageInfo =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(flags.toLong()))
} else {
@Suppress("DEPRECATION")
getPackageInfo(packageName, flags)
}
4 changes: 4 additions & 0 deletions core/common/android/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="version_update_dialog_fail_toast">구글 플레이 스토어 설치가 필요합니다.</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import team.ppac.analytics.action.SettingsAction
import team.ppac.analytics.type.ScreenType
import team.ppac.common.android.base.BaseComposable
import team.ppac.common.android.util.ComposableLifecycle
import team.ppac.common.android.util.checkUpdate
import team.ppac.setting.mvi.SettingIntent
import team.ppac.setting.mvi.SettingSideEffect

Expand Down Expand Up @@ -50,16 +49,15 @@ internal fun SettingRoute(
}
}

LaunchedEffect(key1 = Unit) {
viewModel.intent(SettingIntent.CheckNewAppVersionAvailable(context.checkUpdate()))
}

BaseComposable(viewModel = viewModel) { uiState ->
LaunchedEffect(Unit) {
viewModel.intent(SettingIntent.InitView(context))
}
SettingScreen(
uiState = uiState,
navigateToBack = { viewModel.intent(SettingIntent.ClickBackButton) },
navigateToPrivacyPolicy = { viewModel.intent(SettingIntent.ClickPrivacyPolicy) },
onAppUpdateClick = { viewModel.intent(SettingIntent.ClickAppUpdateButton) }
onAppUpdateClick = { viewModel.intent(SettingIntent.ClickAppUpdateButton(context)) }
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,12 @@ internal fun SettingScreen(
) {
item {
FarmemeBackToolBar(
title = "설정",
onBackIconClick = navigateToBack
title = "설정", onBackIconClick = navigateToBack
)
}
item {
SettingBody(
hasNewAppVersion = uiState.hasNewAppVersion,
onAppUpdateClick = onAppUpdateClick
hasNewAppVersion = uiState.hasNewAppVersion, onAppUpdateClick = onAppUpdateClick
)
}
item {
Expand Down Expand Up @@ -121,12 +119,10 @@ private fun SettingBody(
@Preview
@Composable
private fun SettingScreenPreview() {
SettingScreen(
uiState = SettingUiState.INITIAL_STATE,
SettingScreen(uiState = SettingUiState.INITIAL_STATE,
navigateToBack = {},
navigateToPrivacyPolicy = {},
onAppUpdateClick = {}
)
onAppUpdateClick = {})
}

private fun getVersionName(context: Context): String {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package team.ppac.setting

import android.content.Context
import androidx.lifecycle.SavedStateHandle
import dagger.hilt.android.lifecycle.HiltViewModel
import team.ppac.common.android.base.BaseViewModel
import team.ppac.common.android.util.launchGooglePlayStore
import team.ppac.common.android.util.needToUpdateVersion
import team.ppac.setting.mvi.SettingIntent
import team.ppac.setting.mvi.SettingSideEffect
import team.ppac.setting.mvi.SettingUiState
Expand All @@ -12,6 +15,7 @@ import javax.inject.Inject
class SettingViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
) : BaseViewModel<SettingUiState, SettingSideEffect, SettingIntent>(savedStateHandle) {

override fun createInitialState(savedStateHandle: SavedStateHandle): SettingUiState {
return SettingUiState.INITIAL_STATE
}
Expand All @@ -22,15 +26,24 @@ class SettingViewModel @Inject constructor(

override suspend fun handleIntent(intent: SettingIntent) {
when (intent) {
is SettingIntent.InitView -> checkToUpdateVersion(intent.context)
SettingIntent.ClickBackButton -> onBackButtonClick()
SettingIntent.ClickPrivacyPolicy -> postSideEffect(SettingSideEffect.NavigateToPrivacyPolicy)
SettingIntent.ClickAppUpdateButton -> postSideEffect(SettingSideEffect.UpdateApp)
is SettingIntent.CheckNewAppVersionAvailable -> reduce {
copy(hasNewAppVersion = intent.hasNewAppVersion)
is SettingIntent.ClickAppUpdateButton -> {
if (launchGooglePlayStore(intent.context)) {
postSideEffect(SettingSideEffect.UpdateApp)
}
}
}
}

private fun checkToUpdateVersion(context: Context) {
val needToUpdateVersion = needToUpdateVersion(context)
reduce {
copy(hasNewAppVersion = needToUpdateVersion)
}
}

private fun onBackButtonClick() {
postSideEffect(SettingSideEffect.NavigateToBack)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package team.ppac.setting.mvi

import android.content.Context
import team.ppac.common.android.base.UiIntent

sealed class SettingIntent : UiIntent {
data class InitView(val context: Context) : SettingIntent()
data object ClickBackButton : SettingIntent()
data object ClickPrivacyPolicy : SettingIntent()
data object ClickAppUpdateButton : SettingIntent()
data class CheckNewAppVersionAvailable(val hasNewAppVersion: Boolean) : SettingIntent()
data class ClickAppUpdateButton(val context: Context) : SettingIntent()
}
6 changes: 6 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ activity-ktx = "1.9.0"
google-services = "4.4.2"
firebase-bom = "33.1.1"
firebase-crashlytics = "2.9.9"
firebaseConfigKtx = "22.0.0"
playServicesBase = "18.5.0"

[libraries]
# java
Expand Down Expand Up @@ -137,6 +139,7 @@ activity-ktx = { group = "androidx.activity", name = "activity-ktx", version.ref
firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebase-bom" }
firebase-analytics = { group = "com.google.firebase", name = "firebase-analytics-ktx" }
firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics-ktx" }
firebase-config-ktx = { group = "com.google.firebase", name = "firebase-config-ktx", version.ref = "firebaseConfigKtx" }

# appsflyer
af-android-sdk = { group = "com.appsflyer", name = "af-android-sdk", version.ref = "appsflyer" }
Expand All @@ -146,6 +149,9 @@ paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "and
paging-common = { module = "androidx.paging:paging-common", version.ref = "androidx-paging" }
paging-compose = { module = "androidx.paging:paging-compose", version.ref = "androidx-paging-compose" }

#playstore
play-services-base = { group = "com.google.android.gms", name = "play-services-base", version.ref = "playServicesBase" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
Expand Down