Gradle 7.3.3 / AGP 7.2.1 を対象に、プロジェクト全体を Groovy DSL から Kotlin DSL へ移行した際のポイントをまとめます。Groovy の「メソッドとプロパティの区別が曖昧」「文字列リテラルが勝手にメソッド呼び出しになる」といった挙動は Kotlin DSL では型安全性の高い記述に置き換わります。特に拡張プロパティ(extra)と Maven 公開タスクの書き換えが大きな山場です。
1. ファイル名の変更
各 *.gradle を *.gradle.kts にリネームするだけで Android Studio が Kotlin Script として認識します。
2. ルートレベル build.gradle.kts
apply(from = "config.gradle.kts")
apply(plugin = "com.alibaba.arouter")
buildscript {
repositories {
maven("https://maven.aliyun.com/repository/public")
}
dependencies {
classpath(libs.android.gradlePlugin)
classpath(libs.arouter.register)
}
}
allprojects {
repositories {
maven("https://maven.aliyun.com/repository/public")
}
configurations.configureEach {
resolutionStrategy.force("androidx.appcompat:appcompat:1.4.2")
resolutionStrategy.force("androidx.recyclerview:recyclerview:1.2.1")
}
}
tasks.register<Delete>("clean") {
delete(rootProject.buildDir)
}
3. モジュールレベル build.gradle.kts
plugins {
id("com.android.application")
id("org.greenrobot.greendao")
}
android {
compileSdk = libs.versions.compileSdk.get().toInt()
ndkVersion = libs.versions.ndkVersion.get()
defaultConfig {
applicationId = "com.myapp.sample"
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled = true
externalNativeBuild.cmake {
cppFlags += ""
abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86")
}
}
signingConfigs {
create("release") {
keyAlias = "appkey"
keyPassword = "******"
storeFile = file("key.jks")
storePassword = "******"
}
}
buildTypes {
release {
isMinifyEnabled = true
isZipAlignEnabled = true
signingConfig = signingConfigs["release"]
proguardFiles(
getDefaultProguardFile("proguard-android.txt"),
"proguard-rules.pro",
"proguard-android.pro",
"proguard-third-libs.pro"
)
}
debug {
isMinifyEnabled = false
isDebuggable = true
signingConfig = signingConfigs["release"]
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
buildFeatures.dataBinding = true
greendao.schemaVersion = 1
externalNativeBuild.cmake {
path("src/main/cpp/CMakeLists.txt")
version = "3.10.2"
}
lintOptions.isAbortOnError = false
}
dependencies {
configurations.configureEach {
resolutionStrategy.cacheChangingModulesFor(30, TimeUnit.SECONDS)
}
implementation(libs.glide)
annotationProcessor(libs.glide.compiler)
implementation(project(":easyPhotos"))
implementation(libs.androidx.constraintlayout)
implementation(libs.google.zxing.core) {
exclude(mapOf("group" to "com.google.guava"))
}
}
4. 拡張プロパティの扱い
4.1 値の追加
// パターン1:Map 風
rootProject.extra.apply {
set("userName", "AryaStark")
set("passPhrase", "valarMorghulis")
}
// パターン2:委譲プロパティ
val userName: String by rootProject.extra("AryaStark")
val passPhrase: String by rootProject.extra("valarMorghulis")
// パターン3:ブロックで計算
val userName: String by rootProject.extra {
val tmp = "AryaStark"
tmp
}
4.2 値の取得
// Map 風
val user = rootProject.extra["userName"] as String
val pwd = rootProject.extra["passPhrase"] as String
// 委譲プロパティ(変数名が extra のキーと一致する必要あり)
val userName: String by rootProject.extra
val passPhrase: String by rootProject.extra
5. Maven 公開タスク
5.1 ライブラリモジュール内に記述
plugins {
id("com.android.library")
`maven-publish`
}
android {
publishing {
singleVariant("release") { withSourcesJar() }
}
}
afterEvaluate {
val GROUP_ID = "com.example.sdk"
val ARTIFACT = "core-util"
val VERSION = "1.0.0"
publishing {
publications {
register<MavenPublication>("release") {
from(components["release"])
groupId = GROUP_ID
artifactId = ARTIFACT
version = VERSION
pom.withXml {
println("Upload: $groupId:$artifactId:$version")
configurations["implementation"].allDependencies.forEach {
if (it.version != "unspecified") {
println(" ${it.group}:${it.name}:${it.version}")
}
}
}
}
}
repositories {
maven {
url = uri(rootProject.extra["mavenUrl"] as String)
credentials {
username = rootProject.extra["userName"] as String
password = rootProject.extra["passPhrase"] as String
}
}
}
}
}
5.2 共通スクリプトとして切り出す
build.gradle.kts 側
plugins { id("com.android.library") }
apply(from = "${rootProject.rootDir}/publish.maven.gradle.kts")
publish.maven.gradle.kts 側
import org.gradle.api.publish.PublishingExtension
apply(plugin = "maven-publish")
val catalog: Map<String, Map<String, String>> by rootProject.extra
val lib = catalog[project.name]!!
val sona: Map<String, String> by rootProject.extra
val repoUrl = if (lib["version"]!!.endsWith("SNAPSHOT")) {
sona["snapshotUrl"]!!
} else {
sona["releaseUrl"]!!
}
configure<PublishingExtension> {
publications {
register<MavenPublication>("aar") {
afterEvaluate { from(components["release"]) }
groupId = rootProject.extra["groupId"] as String
artifactId = lib["artifactId"]
version = lib["version"]
pom.withXml {
println("${project.name} → $groupId:$artifactId:$version")
configurations["implementation"].allDependencies.forEach {
if (it.version != "unspecified") {
println(" ${it.group}:${it.name}:${it.version}")
}
}
}
}
}
repositories {
maven {
url = uri(repoUrl)
credentials {
username = sona["userName"]
password = sona["passPhrase"]
}
}
}
}