Skip to content

Commit aeb85b7

Browse files
authored
Merge pull request #158 from YAPP-Github/fix/#129-settings_version_text
[Fix/#129] 설정 화면 버전 표시문제 수정
2 parents 50043f9 + 94a2d27 commit aeb85b7

File tree

17 files changed

+294
-185
lines changed

17 files changed

+294
-185
lines changed

app/build.gradle.kts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ android {
3333
}
3434

3535
defaultConfig {
36-
applicationId = "com.threegap.bitnagil"
37-
3836
val kakaoNativeAppKey =
3937
(properties["kakao.native.app.key"] as? String)
4038
?: System.getenv("KAKAO_NATIVE_APP_KEY")
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.threegap.bitnagil.di.presentation
2+
3+
import com.threegap.bitnagil.presentation.common.version.AndroidApplicationVersionNameProvider
4+
import com.threegap.bitnagil.presentation.common.version.VersionNameProvider
5+
import dagger.Binds
6+
import dagger.Module
7+
import dagger.hilt.InstallIn
8+
import dagger.hilt.components.SingletonComponent
9+
import javax.inject.Singleton
10+
11+
@Module
12+
@InstallIn(SingletonComponent::class)
13+
abstract class VersionNameProviderModule {
14+
@Binds
15+
@Singleton
16+
abstract fun bindVersionNameProvider(androidApplicationVersionNameProvider: AndroidApplicationVersionNameProvider): VersionNameProvider
17+
}

build-logic/convention/src/main/java/com/threegap/bitnagil/convention/AndroidApplicationPlugin.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.threegap.bitnagil.convention
22

33
import com.android.build.api.dsl.ApplicationExtension
44
import com.threegap.bitnagil.convention.extension.configureAppVersion
5+
import com.threegap.bitnagil.convention.extension.configureApplicationId
56
import com.threegap.bitnagil.convention.extension.configureComposeAndroid
67
import com.threegap.bitnagil.convention.extension.configureKotlinAndroid
78
import org.gradle.api.Plugin
@@ -23,6 +24,7 @@ class AndroidApplicationPlugin : Plugin<Project> {
2324
configureKotlinAndroid(this)
2425
configureComposeAndroid(this)
2526
configureAppVersion()
27+
configureApplicationId()
2628
with(defaultConfig) {
2729
targetSdk = libs.findVersion("targetSdk").get().requiredVersion.toInt()
2830
versionCode = libs.findVersion("versionCode").get().requiredVersion.toInt()

build-logic/convention/src/main/java/com/threegap/bitnagil/convention/AndroidLibraryPlugin.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.threegap.bitnagil.convention
22

33
import com.android.build.gradle.LibraryExtension
44
import com.threegap.bitnagil.convention.extension.configureAppVersion
5+
import com.threegap.bitnagil.convention.extension.configureApplicationId
56
import com.threegap.bitnagil.convention.extension.configureKotlinAndroid
67
import com.threegap.bitnagil.convention.extension.configureKotlinCoroutine
78
import org.gradle.api.Plugin
@@ -19,6 +20,7 @@ class AndroidLibraryPlugin : Plugin<Project> {
1920
configureKotlinAndroid(this)
2021
configureKotlinCoroutine(this)
2122
configureAppVersion()
23+
configureApplicationId()
2224
}
2325
}
2426
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.threegap.bitnagil.convention.extension
2+
3+
import com.android.build.api.dsl.ApplicationExtension
4+
import com.android.build.api.dsl.LibraryExtension
5+
import org.gradle.api.Project
6+
import org.gradle.kotlin.dsl.findByType
7+
8+
internal fun Project.configureApplicationId() {
9+
val applicationId = "com.threegap.bitnagil"
10+
11+
extensions.findByType<ApplicationExtension>()?.let { appExtension ->
12+
appExtension.defaultConfig {
13+
this.applicationId = applicationId
14+
}
15+
}
16+
17+
extensions.findByType<LibraryExtension>()?.let { libExtension ->
18+
libExtension.apply {
19+
defaultConfig {
20+
buildConfigField("String", "APPLICATION_ID", "\"$applicationId\"")
21+
}
22+
buildFeatures {
23+
buildConfig = true
24+
}
25+
}
26+
}
27+
}

gradle/libs.versions.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ junit = "4.13.2"
4848
junitVersion = "1.2.1"
4949
espressoCore = "3.6.1"
5050

51+
## app-update
52+
app-update = "2.1.0"
53+
5154
## Other
5255
material = "1.12.0"
5356
orbit = "10.0.0"
@@ -125,6 +128,10 @@ kotlin-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coro
125128
coil-compose = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" }
126129
coil-network = { group = "io.coil-kt.coil3", name = "coil-network-okhttp", version.ref = "coil" }
127130

131+
## app-update
132+
app-update = { group = "com.google.android.play", name = "app-update", version.ref = "app-update" }
133+
app-update-ktx = { group = "com.google.android.play", name = "app-update-ktx", version.ref = "app-update" }
134+
128135
## Other
129136
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
130137
kakao-v2-user = { group = "com.kakao.sdk", name = "v2-user", version.ref = "kakaoLogin" }
@@ -190,6 +197,11 @@ coil = [
190197
"coil-network"
191198
]
192199

200+
app-update = [
201+
"app-update",
202+
"app-update-ktx"
203+
]
204+
193205
[plugins]
194206
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
195207
android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }

presentation/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ dependencies {
2121
implementation(libs.lottie.compose)
2222
implementation(libs.bundles.coil)
2323
implementation(libs.accompanist.permissions)
24+
implementation(libs.bundles.app.update)
2425

2526
testImplementation(libs.junit)
2627
testImplementation(libs.kotlin.coroutines.test)
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package com.threegap.bitnagil.presentation.common.playstore
2+
3+
import android.content.ActivityNotFoundException
4+
import android.content.Context
5+
import android.content.Intent
6+
import androidx.activity.ComponentActivity
7+
import androidx.compose.runtime.Composable
8+
import androidx.compose.runtime.LaunchedEffect
9+
import androidx.compose.runtime.getValue
10+
import androidx.compose.runtime.mutableStateOf
11+
import androidx.compose.runtime.remember
12+
import androidx.compose.runtime.setValue
13+
import androidx.compose.ui.platform.LocalContext
14+
import androidx.core.net.toUri
15+
import androidx.lifecycle.lifecycleScope
16+
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
17+
import com.google.android.play.core.install.model.AppUpdateType
18+
import com.google.android.play.core.install.model.UpdateAvailability
19+
import com.threegap.bitnagil.presentation.BuildConfig
20+
import kotlinx.coroutines.delay
21+
import kotlinx.coroutines.launch
22+
import kotlinx.coroutines.suspendCancellableCoroutine
23+
import kotlin.coroutines.resume
24+
import kotlin.system.exitProcess
25+
26+
private const val PACKAGE_NAME = BuildConfig.APPLICATION_ID
27+
private const val GOOGLE_PLAY_PACKAGE = "com.android.vending"
28+
private const val APP_EXIT_DELAY = 500L
29+
30+
fun openAppInPlayStore(
31+
activity: ComponentActivity?,
32+
shouldFinishApp: Boolean = true,
33+
) {
34+
activity?.let {
35+
val isSuccess = tryOpenPlayStore(it) || tryOpenWebBrowser(it)
36+
37+
if (isSuccess && shouldFinishApp) {
38+
finishAppWithDelay(it)
39+
}
40+
}
41+
}
42+
43+
private fun tryOpenPlayStore(activity: ComponentActivity): Boolean =
44+
try {
45+
val intent = createPlayStoreIntent()
46+
activity.startActivity(intent)
47+
true
48+
} catch (e: ActivityNotFoundException) {
49+
false
50+
}
51+
52+
private fun tryOpenWebBrowser(activity: ComponentActivity): Boolean =
53+
try {
54+
val intent = createWebIntent()
55+
activity.startActivity(intent)
56+
true
57+
} catch (e: Exception) {
58+
false
59+
}
60+
61+
private fun createPlayStoreIntent(): Intent =
62+
Intent(
63+
Intent.ACTION_VIEW,
64+
"market://details?id=$PACKAGE_NAME".toUri(),
65+
).apply {
66+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
67+
setPackage(GOOGLE_PLAY_PACKAGE)
68+
}
69+
70+
private fun createWebIntent(): Intent =
71+
Intent(
72+
Intent.ACTION_VIEW,
73+
"https://play.google.com/store/apps/details?id=$PACKAGE_NAME".toUri(),
74+
).apply {
75+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
76+
}
77+
78+
private fun finishAppWithDelay(activity: ComponentActivity) {
79+
activity.lifecycleScope.launch {
80+
delay(APP_EXIT_DELAY)
81+
activity.finishAffinity()
82+
exitProcess(0)
83+
}
84+
}
85+
86+
@Composable
87+
fun updateAvailable(): UpdateAvailableState {
88+
val context = LocalContext.current
89+
var isUpdateAvailable by remember { mutableStateOf(UpdateAvailableState.NONE) }
90+
91+
LaunchedEffect(Unit) {
92+
isUpdateAvailable = context.checkForUpdateAvailability()
93+
}
94+
95+
return isUpdateAvailable
96+
}
97+
98+
private suspend fun Context.checkForUpdateAvailability(): UpdateAvailableState = suspendCancellableCoroutine { continuation ->
99+
val appUpdateManager = AppUpdateManagerFactory.create(this)
100+
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
101+
102+
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
103+
if (!continuation.isActive) return@addOnSuccessListener
104+
105+
val isAvailable = appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
106+
107+
val isAllowed = appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) ||
108+
appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)
109+
110+
val state = if (isAvailable && isAllowed) UpdateAvailableState.NEED_UPDATE else UpdateAvailableState.LATEST
111+
continuation.resume(state)
112+
}
113+
114+
appUpdateInfoTask.addOnFailureListener {
115+
if (continuation.isActive) {
116+
continuation.resume(UpdateAvailableState.NONE)
117+
}
118+
}
119+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.threegap.bitnagil.presentation.common.playstore
2+
3+
enum class UpdateAvailableState {
4+
LATEST, NEED_UPDATE, NONE
5+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.threegap.bitnagil.presentation.common.version
2+
3+
import com.threegap.bitnagil.presentation.BuildConfig
4+
import javax.inject.Inject
5+
6+
class AndroidApplicationVersionNameProvider @Inject constructor() : VersionNameProvider {
7+
override fun getVersionName(): String {
8+
val majorVersion = BuildConfig.VERSION_MAJOR
9+
val minorVersion = BuildConfig.VERSION_MINOR
10+
val patchVersion = BuildConfig.VERSION_PATCH
11+
12+
return "$majorVersion.$minorVersion.$patchVersion"
13+
}
14+
}

0 commit comments

Comments
 (0)