今までなんとなくコピペとかコピペとかコピペで書いていた gradle 。
Groovy とか言う音ゲーのタイトルっぽいスクリプトで書かれています。
なんとその gradle が Kotlin で記述できるではありませんか!
これで少しは理解に身が入ると言うもの。さっそく試したいと思いました。
Kotlin DSL ??
- Domain-Specific Language
特定の課題を解決するために特化された言語
SQL や HTML, Groovy なんかも DSL になるらしいですね。
Kotlin でスクリプトが書ける機能です。
Migration
今回は元々あるプロジェクトへの導入方法になります。
Environment
- Android Studio 3.5.3
- Gradle 6.0.1
- Kotlin 1.3.61
- JDK 8
Rename and Rewrite
ほぼほぼ Android Studio の New Project で自動生成される gradle を書き換えます。
1. settings.gradle -> settings.gradle.kts
に Rename and Rewrite
include(":app")
rootProject.name = "MyApplication"
2. ルートレベルの build.gradle -> build.gradle.kts
に Rename and Rewrite
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:3.5.3")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61")
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task<Delete>("clean") {
delete(rootProject.buildDir)
}
3. モジュール内の build.gradle -> build.gradle.kts
に Rename and Rewrite
plugins {
id("com.android.application")
kotlin("android")
kotlin("android.extensions")
}
android {
compileSdkVersion(29)
buildToolsVersion = "29.0.0"
defaultConfig {
applicationId = "<ApplicationId>"
minSdkVersion(23)
targetSdkVersion(29)
versionCode = 1
versionName = "0.1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
}
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61")
implementation("androidx.appcompat:appcompat:1.1.0")
implementation("androidx.core:core-ktx:1.2.0-rc01")
implementation("androidx.constraintlayout:constraintlayout:2.0.0-beta2")
testImplementation("junit:junit:4.12")
androidTestImplementation("androidx.test.ext:junit:1.1.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0")
}
4. Sync Now !!!😎
Success!!😎
依存関係をまとめる
これで Kotliner として一歩前に進んだ気がします。やったね。
意気揚々と Android 開発のバイブル DroidKaigi のリポジトリを見に行くと何やら見た事ない書き方が。
conference-app-2020/build.gradle at master · DroidKaigi/conference-app-2020 · GitHub
import dependencies.Dep
...
dependencies {
...
implementation Dep.Kotlin.stdlibJvm
implementation Dep.AndroidX.appCompat
implementation Dep.AndroidX.coreKtx
implementation Dep.AndroidX.constraint
implementation Dep.AndroidX.activityKtx
...
}
Packages?? Dep?? 🤔
依存関係を定義して使い回す
マルチモジュールで開発する時にライブラリの情報とかがいろんなところに散りばめられて管理が大変らしい。
それらを buildSrc
に纏めると一元管理できていいよね😂 との事。
たしかに見やすくなっているので実際に試してみました。
1. プロジェクトのルートに buildSrc
ディレクトリを作成
まず object を定義するモジュール? 用のディレクトリを作成します。
-
普通にディレクトリを作成します 。
( Android Studio ではNew -> Directory -> buildSrc
)
Add Module とかではない。(最初間違えました。。。)
2. Sync Now !!!😎
.gradle
, build
ができあがると思います。
3. build.gradle.kts
を作成
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}
4. 変数の定義をするファイルを作成
今回は src/main/kotlin/dependencies
配下に置きました。
これも普通に src -> main -> kotlin -> ...
とディレクトリを作成していきます。
あとはソースファイルを作成していつもの様に変数定義します。
我らが DroidKaigi さんは Package 情報も切り出していたので真似してみました。
object Dep {
object Plugin {
val android = "com.android.tools.build:gradle:3.5.3"
val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Kotlin.version}"
val safeArgs = "androidx.navigation:navigation-safe-args-gradle-plugin:${AndroidX.Navigation.version}"
}
object Test {
val junit = "junit:junit:4.12"
val androidJunit = "androidx.test.ext:junit:1.1.1"
val espressoCore = "androidx.test.espresso:espresso-core:3.2.0"
}
object Kotlin {
const val version = "1.3.61"
val stdlibJdk = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$version"
}
object AndroidX {
val appCompat = "androidx.appcompat:appcompat:1.1.0"
val coreKtx = "androidx.core:core-ktx:1.2.0-rc01"
val constraint = "androidx.constraintlayout:constraintlayout:2.0.0-beta2"
}
}
object Packages {
const val id = "<Application Id>"
const val debugIdSuffix = ".debug"
object SdkVersion {
const val target = 29
const val compile = 29
const val min = 21
}
object Version {
private const val major = 0
private const val minor = 1
private const val build = 0
val code = (major * 100 + minor * 10 + build)
val name = "$major.$minor.$build"
}
}
5. Sync Now !!!😎
準備できました。
あとは gradle ファイル内で import して使うだけ。
6. import
import dependencies.Packages
import dependencies.Dep
android {
compileSdkVersion(Packages.SdkVersion.compile)
buildToolsVersion = Packages.SdkVersion.compile.toString()
defaultConfig {
applicationId = Packages.id
minSdkVersion(Packages.SdkVersion.min)
targetSdkVersion(Packages.SdkVersion.target)
versionCode = Packages.Version.code
versionName = Packages.Version.name
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
}
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation(Dep.Kotlin.stdlibJdk)
implementation(Dep.AndroidX.appCompat)
implementation(Dep.AndroidX.coreKtx)
implementation(Dep.AndroidX.constraint)
testImplementation(Dep.Test.junit)
androidTestImplementation(Dep.Test.androidJunit)
androidTestImplementation(Dep.Test.espressoCore)
}
この調子でルートレベルの gradle も書き換えます
import dependencies.Dep
buildscript {
dependencies {
classpath(Dep.Plugin.android)
classpath(Dep.Plugin.kotlin)
}
}
7. Sync now !!!😎
Succe...ん??
org.gradle.internal.exceptions.LocationAwareException: Build file '../build.gradle.kts' line: 10
Script compilation errors:
Line 10: classpath(Dep.Plugin.android)
^ Unresolved reference: Dep
Line 11: classpath(Dep.Plugin.kotlin)
^ Unresolved reference: Dep
あれ?参照できない??
補完はちゃんと効いてるしコンパイルした時だけエラーになる。。。
buildSrc の build が走ったあとの Configuration でエラーだし。。。
Android Studio を 3.6 にあげてもだめ。。。
試しに src/main/kotlin 配下に置くか build.gradle を Groovy で書くと通りました。なぜだ。。。
ひとまず Plugin 関連の定義だけ別ファイルに切り出して直下に置く対応をしました。
Conclusion
マルチモジュールではない場合の恩恵はそこまでなのかもしれませんが、
補完が効くので普通に書きやすいでした。
あとエラーの箇所もわかりやすいのでよき。
新しい事を学習するのは楽しいですね。(遅)
しかし、今年の DroidKaigi リポジトリでは Groovy で書かれていましたがどうしてなんでしょう。( Plugin の参照エラーのため?? )
この記事を投稿するほんの少し前に Issue あげられてました!!
名乗りあげようと思ったらもう Assigne 決まってて残念です…
今回やったことの他、Jetpack のライブラリ等、ナウなインプルをスタディするために
LINE の既読無視をするためのアプリを仕事の合間に開発中です。
GitHub - tick-taku/NotificationWatcher
次回は Room の勉強か coroutine の勉強か。
たぶん Room かな。。。
参考
【Android】dependenciesをIDE補完で記述する - Qiita
The New Way of Writing Build Gradle with Kotlin DSL
【Android】buildSrcを使ってライブラリの定義をまとめる | ITcowork Staff Blog
GitHub - DroidKaigi/conference-app-2020: The Official Conference App for DroidKaigi 2020 Tokyo