#1 ๊ฐ์
#1-1 WhatใWhy
Now in Android | Android Developers
์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค์ผ๋ก ์ฝํ ์ธ ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฅํ์ธ์. Now in Android ์ฑ, Play ์คํ ์ด์ ์ถ์ Now in Android๋ ์์ ํ
developer.android.com
Now in Android๋ Android ์ค๊ณ ๋ฐ ๊ฐ๋ฐ ๊ถ์ฅ์ฌํญ๋๋ก ๋ง๋ '๊ณต์์ ์ธ ์ํ' ์ฑ์ด๋ค (์์ค ์ฝ๋). ๊ฐ์ธ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ ์ค, ๋ด ํ๋ก์ ํธ์ ๋ฒ์ ์นดํ๋ก๊ทธ ์ ํ๋กํผํฐ๋ช ๊ณผ Now in Android์ ๋ฒ์ ์นดํ๋ก๊ทธ ์ ํ๋กํผํฐ๋ช ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ๋ฅผ ํ์ธํ๋ค. ๋๋ Now in Android์ ์คํ์ผ์ ๋ฐ๋ผ๊ฐ ๊ฒ์ด๋ฏ๋ก, ํ๋กํผํฐ๋ช ๊น์ง ๋๊ฐ์ด ๋ง์ถ๋ฉด ์ข๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ๊ทธ๋์ ์ด๋ฌํ '๋ถ์ผ์น'๋ฅผ ์ถ๋ ฅํ๋ ๊ฒ์ฆ์ฉ ์ฝํ๋ฆฐ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค์๋ค.
#1-2 tomlj ๋ผ์ด๋ธ๋ฌ๋ฆฌ
GitHub - tomlj/tomlj: A Java parser for Tom's Obvious, Minimal Language (TOML).
A Java parser for Tom's Obvious, Minimal Language (TOML). - tomlj/tomlj
github.com
"tomlj"๋ Java(์ Kotlin)์์ ์ฌ์ฉํ ์ ์๋ TOML ํ์ผ ํ์ฑ์ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค. ๋ฒ์ ์นดํ๋ก๊ทธ๋ TOML ํ์ฅ์๋ค. ๊ทธ๋์ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํ๋ค (์ฐธ๊ณ : Maven Repository์ tomlj ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ด์ง).
#2 ์ฝ๋
#2-1 ์คํฌ๋ฆฝํธ
import org.tomlj.Toml
import org.tomlj.TomlTable
import java.nio.file.Paths
data class TomlElement(
val propertyName: String,
val group: String?,
val name: String?,
val module: String?,
val id: String?,
val versionRef: String?
) {
val identifier: String? = if (group != null && name != null) {
"$group:$name"
} else {
module ?: id
}
fun isStrictlyEqualTo(other: TomlElement): Boolean {
return propertyName == other.propertyName
&& group == other.group
&& name == other.name
&& module == other.module
&& id == other.id
&& versionRef == other.versionRef
}
fun makeTomlLine(): String {
var tomlLine = "$propertyName = { "
group?.let { tomlLine += "group = \"${it}\", " }
name?.let { tomlLine += "name = \"${it}\", " }
module?.let { tomlLine += "module = \"${it}\", " }
id?.let { tomlLine += "id = \"${it}\", " }
versionRef?.let { tomlLine += "version.ref = \"${it}\", " }
tomlLine = tomlLine.removeSuffix(", ") + " }"
return tomlLine
}
}
const val MY_PROJECT_VERSION_CATALOG_PATH = "C:\\prj\\AndroidStudioProjects\\my-project-example\\gradle\\libs.versions.toml"
const val NIA_VERSION_CATALOG_PATH = "C:\\prj\\AndroidStudioProjects\\nowinandroid\\gradle\\libs.versions.toml"
fun main() {
val myList = getTomlElementList(
versionCatalogPath = MY_PROJECT_VERSION_CATALOG_PATH
)?.filter { it.identifier != null }
val niaList = getTomlElementList(
versionCatalogPath = NIA_VERSION_CATALOG_PATH
)?.filter { it.identifier != null }
var result = ""
myList?.forEach { myElement ->
val niaElement = niaList?.find { niaElement ->
(myElement.identifier == niaElement.identifier) and
!myElement.isStrictlyEqualTo(niaElement)
}
if (niaElement != null) {
val tomlLine1 = myElement.makeTomlLine()
val tomlLine2 = niaElement.makeTomlLine()
result += " [My] $tomlLine1\n[Nia] $tomlLine2\n\n"
}
}
println(result)
}
fun getTomlElementList(versionCatalogPath: String): List<TomlElement>? {
val tomlPath = Paths.get(versionCatalogPath)
val toml = Toml.parse(tomlPath)
val librariesMap = toml.getTable("libraries")?.toMap() ?: emptyMap()
val pluginsMap = toml.getTable("plugins")?.toMap() ?: emptyMap()
val list = (librariesMap + pluginsMap).mapNotNull { (key, value) ->
val isValueTomlTableType = value is TomlTable // TomlTable ํ์ผ๋ก ํ๋ณํ์ด ๊ฐ๋ฅํ๊ฐ?
if (!isValueTomlTableType) {
return@mapNotNull null
}
val group = value.getString("group")
val name = value.getString("name")
val module = value.getString("module")
val id = value.getString("id")
val versionRef = value.getString("version.ref")
TomlElement(
propertyName = key,
group = group,
name = name,
module = module,
id = id,
versionRef = versionRef
)
}
return list
}
๋จผ์ build.gradle์ dependencies์ implementation("org.tomlj:tomlj:1.1.0")์ ๊ฐ์ ๊ตฌ๋ฌธ์ ์ถ๊ฐํด์ฃผ์ด์ผ, import๋ฌธ์ ์ธ์ํด์ ์์ ์ฝ๋๊ฐ ์๋ํ๋ค. ์๋ฌดํผ MY_PROJECT_VERSION_CATALOG_PATH์ ๋ด ํ๋ก์ ํธ์ ๋ฒ์ ์นดํ๋ก๊ทธ ํ์ผ ๊ฒฝ๋ก๋ฅผ, NIA_VERSION_CATALOG_PATH์ Now in Android ํ๋ก์ ํธ์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ ๊ณ ์คํ์ํค๋ฉด ๋๋ค.
"libraries" ํ ์ด๋ธ์ ํ๋กํผํฐ๋ช (key๊ฐ)์ด ๋ค๋ฅธ ๊ฒฝ์ฐ ๋ฟ๋ง ์๋๋ผ, version.ref ์ ํ ๋น๋ ๋ฌธ์์ด์ด ๋ค๋ฅธ ๊ฒฝ์ฐ๋ ๊ฐ์งํ๊ฒํ๋ค. ์ด ๊ฒฝ์ฐ๋, version.ref ์ ํ ๋น๋๋ "versions" ํ ์ด๋ธ์ ํ๋กํผํฐ๋ช (key๊ฐ)์ (Now in Android์ ๋๊ฐ๊ฒ) ์์ ํ๊ธฐ ์ํจ์ด๋ค. ๋ ํ ์ชฝ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ด๋ฆ์ "group" ๋ฐ "name"์ ๋๋ ๋ด์๋๋ฐ ๋ค๋ฅธ ์ชฝ์์ "module"์ ํต์งธ๋ก ๋ด์ ๊ฒฝ์ฐ ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋ฐ๋์ ๊ฒฝ์ฐ๋ ๊ฐ์งํ๊ฒ ๋ง๋ค์๋ค.
#2-2 ์คํ ๊ฒฐ๊ณผ
[My] androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
[Nia] androidx-compose-ui-test = { group = "androidx.compose.ui", name = "ui-test-junit4" }
[My] androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
[Nia] androidx-test-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidxEspresso" }
[My] hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltVersion" }
[Nia] hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
[My] androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
[Nia] androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
[My] androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "materialIconsExtended" }
[Nia] androidx-compose-material-iconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" }
[My] androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" }
[Nia] androidx-lifecycle-viewModelCompose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" }
[My] androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
[Nia] androidx-compose-ui-testManifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
[My] androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
[Nia] androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
[My] androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
[Nia] room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
[My] truth = { module = "com.google.truth:truth", version.ref = "truthVersion" }
[Nia] truth = { group = "com.google.truth", name = "truth", version.ref = "truth" }
[My] androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
[Nia] androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidxActivity" }
[My] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
[Nia] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidxCore" }
[My] androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomRuntime" }
[Nia] room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
[My] androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
[Nia] androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidxAppCompat" }
[My] androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationRuntimeKtx" }
[Nia] androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "androidxNavigation" }
[My] androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomRuntime" }
[Nia] room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
[My] androidx-ui-util = { group = "androidx.compose.ui", name = "ui-util" }
[Nia] androidx-compose-ui-util = { group = "androidx.compose.ui", name = "ui-util" }
[My] androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
[Nia] androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
[My] androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" }
[Nia] androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "androidxHiltNavigationCompose" }
[My] android-library = { id = "com.android.library", version.ref = "agp" }
[Nia] android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }
[My] kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
[Nia] compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
[My] android-application = { id = "com.android.application", version.ref = "agp" }
[Nia] android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
[My] hilt = { id = "com.google.dagger.hilt.android", version.ref = "hiltVersion" }
[Nia] hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
์ถ๋ ฅ๋ ๋ด์ฉ์ ๋ฐํ์ผ๋ก ๋ด ํ๋ก์ ํธ์ ํ๋กํผํฐ๋ช ๋ค์ ์์ ํ๋ค. ์์ ํ ๋ค์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํ์์ผ๋ดค๋๋ฐ, ๋น์ฐํ๊ฒ ์ง๋ง (๋ค๋ฅธ ์ ์ด ์์ํ ๋) ์๋ฌด๊ฒ๋ ์ถ๋ ฅ๋์ง ์์๋ค.