ビルド構成を Groovy から Kotlin に移行する

Android Gradle プラグイン 4.0 では、Gradle 構成ファイルで従来使用されていたプログラミング言語である Groovy に代わって、Gradle ビルド構成で Kotlin を使用するためのサポートが追加されました。

Kotlin の方が可読性が高く、コンパイル時のチェックと IDE サポートが優れているため、今後、Gradle スクリプトの記述には Groovy よりも Kotlin を推奨します。

Groovy と比較して、Kotlin は今のところ、Android Studio のコードエディタとの統合という面で優れていますが、Kotlin を使用したビルドは Groovy を使用したビルドよりも遅くなる傾向があるため、ビルド パフォーマンスを考慮したうえで移行を検討する必要があります。

このページでは、Android アプリの Gradle ビルドファイルを Groovy から Kotlin に変換するための基本的な情報を提供します。包括的な移行ガイドについては、Gradle の公式ドキュメントをご覧ください。

タイムライン

Android Studio Giraffe 以降、新しいプロジェクトでは、ビルド構成にデフォルトで Kotlin DSL(build.gradle.kts)が使用されます。これにより、構文のハイライト表示、コード補完、宣言へのナビゲーションなど、Groovy DSL(build.gradle)よりも優れた編集エクスペリエンスを実現できます。詳細については、Gradle Kotlin DSL Primer をご覧ください。

よく使用する用語

Kotlin DSL: 主に Android Gradle プラグイン Kotlin DSL のことを指します。基となる Gradle Kotlin DSL を指すこともあります。

この移行ガイドでは、「Kotlin」と「Kotlin DSL」は同じ意味で使用されます。同様に、「Groovy」と「Groovy DSL」は同じ意味で使用されます。

スクリプト ファイルの名称

スクリプト ファイルの拡張子は、ビルドファイルが記述されている言語に基づきます。

  • Groovy で記述した Gradle ビルドファイルは、ファイル名拡張子 .gradle を使用します。
  • Kotlin で記述した Gradle ビルドファイルは、ファイル名拡張子 .gradle.kts を使用します。

構文を変換する

Groovy と Kotlin の構文には一部異なる点があるため、それらの違いをビルド スクリプト全体に反映する必要があります。

メソッド呼び出しにかっこを追加する

メソッド呼び出しのかっこは、Groovy では省略できますが Kotlin では必須です。構成を移行するには、かっこが省略されているメソッド呼び出しにかっこを追加します。Groovy で設定を構成する場合のコードは次のようになっています。

compileSdkVersion 30

これを Kotlin で記述すると次のようなコードになります。

compileSdkVersion(30)

代入呼び出しに = を追加する

Groovy DSL では、プロパティを代入する際の代入演算子 = を省略できますが、これは Kotlin では必須です。Groovy でプロパティを代入する場合のコードは次のようになっています。

java {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
}

Kotlin でプロパティを代入するには次のようなコードを記述します。

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

文字列を変換する

Groovy と Kotlin では、文字列に関して以下のような違いがあります。

  • 文字列の二重引用符: Groovy では一重引用符を使用して文字列を定義できますが、Kotlin では二重引用符を使用する必要があります。
  • ドット表記の文字列補間: Groovy ではドット表記の文字列補間に接頭辞 $ を使用できますが、Kotlin ではドット表記を中かっこで囲む必要があります。たとえば、Groovy では次のスニペットのように $project.rootDir を使用できます。

        myRootDirectory = "$project.rootDir/tools/proguard-rules-debug.pro"
        

    一方、Kotlin では project.rootDir ではなく projecttoString() を呼び出します。ルート ディレクトリの値を取得するには、${project.rootDir} のように中かっこで囲みます。

        myRootDirectory = "${project.rootDir}/tools/proguard-rules-debug.pro"
        

    詳細については、Kotlin ドキュメントの文字列テンプレートをご覧ください。

ファイル拡張子を変更する

コンテンツを移行する際に、各ビルドファイルに .kts を追加します。たとえば、ビルドファイル settings.gradle を選択したら、ファイル名を settings.gradle.kts に変更して、ファイルのコンテンツを Kotlin に変換します。各ビルドファイルの移行後もプロジェクトがコンパイルされていることを確認します。

まずは小さなファイルの移行から始めて作業に慣れてください。プロジェクト内に Kotlin と Groovy のビルドファイルを混在させることもできるため、時間をかけて慎重に移行してください。

defval または var で置き換える

Kotlin で変数を定義できるよう、defval または var で置き換えます。Groovy では次のように変数を宣言します。

def building64Bit = false

これを Kotlin で記述すると次のようなコードになります。

val building64Bit = false

ブール値プロパティに接頭辞 is を追加する

Groovy では、プロパティ名に基づいてプロパティ推定ロジックを使用します。ブール値プロパティ foo の場合、推定メソッドgetFoosetFoo、または isFoo になります。Kotlin では推定メソッドがサポートされていないため、プロパティ名を推定メソッド名に変更する必要があります。たとえば、buildTypes DSL ブール値要素には、接頭辞 is を追加する必要があります。Groovy では、次のようなコードでブール値プロパティを設定します。

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            ...
        }
        debug {
            debuggable true
            ...
        }
    ...

これを Kotlin で記述すると次のようなコードになります。プロパティには接頭辞 is が追加されています。

android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true
            ...
        }
        getByName("debug") {
            isDebuggable = true
            ...
        }
    ...

リストとマップを変換する

Groovy と Kotlin では、リストとマップを定義する構文が異なります。Groovy では [] を使用しますが、Kotlin では listOf または mapOf を使用してコレクション作成メソッドを明示的に呼び出します。移行時には、[]listOf または mapOf に置き換える必要があります。

Groovy では、次のようなコードでリストを定義します。

jvmOptions += ["-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError</code>"]

これを Kotlin で記述すると次のようなコードになります。

jvmOptions += listOf("-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError")

Groovy では、次のようなコードでマップを定義します。

def myMap = [key1: 'value1', key2: 'value2']

これを Kotlin で記述すると次のようなコードになります。

val myMap = mapOf("key1" to "value1", "key2" to "value2")

ビルドタイプを設定する

Kotlin DSL で暗黙的に使用できるビルドタイプは debug と release のみです。これら以外のすべてのカスタム ビルドタイプは手動で作成する必要があります。

Groovy では、debug や release 以外にも、先に作成していなくても使用できるビルドタイプがあります。次のコード スニペットに、Groovy でビルドタイプ debugreleasebenchmark を使用する構成を示します。

buildTypes {
 debug {
   ...
 }
 release {
   ...
 }
 benchmark {
   ...
 }
}

Kotlin で同じ構成を作成するには、ビルドタイプ benchmark を明示的に作成する必要があります。

buildTypes {
 debug {
   ...
 }

 release {
   ...
 }
 register("benchmark") {
    ...
 }
}

buildscript から plugins ブロックに移行する

ビルドで buildscript {} ブロックを使用してプロジェクトにプラグインを追加している場合は、代わりに plugins {} ブロックを使用するようにリファクタリングする必要があります。plugins {} ブロックを使用すると、プラグインを簡単に適用できます。また、バージョン カタログと連携して動作します。

また、ビルドファイルで plugins {} ブロックを使用すると、ビルドが失敗しても Android Studio はコンテキストを認識します。このコンテキストは、Studio IDE がコード補完や他の有用な提案を行えることから、Kotlin DSL ファイルを修正する場合に役立ちます。

プラグイン ID を確認する

buildscript {} ブロックは、プラグインの Maven 座標com.android.tools.build:gradle:7.4.0 など)を使用してプラグインをビルド クラスパスに追加しますが、plugins {} ブロックは代わりにプラグイン ID を使用します。

ほとんどのプラグインでは、プラグイン ID は apply plugin を使用してプラグインを適用するときに使用される文字列です。たとえば、次のプラグイン ID は Android Gradle プラグインの一部です。

  • com.android.application
  • com.android.library
  • com.android.lint
  • com.android.test

プラグインの完全なリストは、Google Maven リポジトリで確認できます。

Kotlin プラグインは複数のプラグイン ID で参照できます。名前空間方式のプラグイン ID を使用することをおすすめします。次の表に従って、省略形から名前空間方式のプラグイン ID にリファクタリングします。

省略形のプラグイン ID 名前空間方式のプラグイン ID
kotlin org.jetbrains.kotlin.jvm
kotlin-android org.jetbrains.kotlin.android
kotlin-kapt org.jetbrains.kotlin.kapt
kotlin-parcelize org.jetbrains.kotlin.plugin.parcelize

Gradle プラグイン ポータルMaven セントラル リポジトリGoogle Maven リポジトリでプラグインを検索することもできます。プラグイン ID の仕組みについて詳しくは、カスタムの Gradle プラグインを開発するをご覧ください。

リファクタリングを実行する

使用するプラグインの ID を確認したら、次の手順を行います。

  1. buildscript {} ブロックでプラグインのリポジトリがまだ宣言されている場合は、代わりに settings.gradle ファイルに移動します。

  2. プラグインを最上位の build.gradle ファイルの plugins {} ブロックに追加します。ここでは、プラグインの ID とバージョンを指定する必要があります。プラグインをルート プロジェクトに適用する必要がない場合は、apply false を使用します。

  3. 最上位の build.gradle.kts ファイルから classpath エントリを削除します。

  4. モジュール レベルの build.gradle ファイルの plugins {} ブロックにプラグインを追加して、プラグインを適用します。バージョンはルート プロジェクトから継承されるため、ここで指定する必要があるのはプラグインの ID のみです。

  5. モジュール レベルの build.gradle ファイルから、プラグインの apply plugin 呼び出しを削除します。

たとえば、この設定では buildscript {} ブロックを使用します。

// Top-level build.gradle file
buildscript {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.4.0")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0")
        ...
    }
}

// Module-level build.gradle file
apply(plugin: "com.android.application")
apply(plugin: "kotlin-android")

これは、plugins {} ブロックを使用した同等の設定です。

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.4.0' apply false
   id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   id 'org.jetbrains.kotlin.android'
   ...
}

// settings.gradle
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

plugins ブロックを変換する

plugins {} ブロックからプラグインを適用する方法は、Groovy と Kotlin で似ています。次のコードは、バージョン カタログを使用している場合に、Groovy でプラグインを適用する方法を示しています。

// Top-level build.gradle file
plugins {
   alias libs.plugins.android.application apply false
   ...
}

// Module-level build.gradle file
plugins {
   alias libs.plugins.android.application
   ...
}

Kotlin で同じ処理を行うコードは次のようになります。

// Top-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application) apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application)
   ...
}

次のコードは、バージョン カタログを使用していない場合に、Groovy でプラグインを適用する方法を示しています。

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.3.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   ...
}

Kotlin で同じ処理を行うコードは次のようになります。

// Top-level build.gradle.kts file
plugins {
   id("com.android.application") version "7.3.0" apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   id("com.android.application")
   ...
}

plugins {} ブロックの詳細については、Gradle ドキュメントのプラグインの適用についての説明をご覧ください。

その他

その他の機能の Kotlin コードサンプルについては、以下のドキュメント ページをご覧ください。

既知の問題

現時点での既知の問題は、Kotlin の方が Groovy よりもビルド速度が遅くなる可能性があることです。

問題を報告する方法

問題の優先順位の判断に必要な情報を提供する方法については、ビルドツールと Gradle バグの詳細をご覧ください。その後、Google の公開 Issue Tracker を使用してバグを報告します。

その他のリソース

Kotlin で記述された Gradle ビルドファイルの実例については、GitHub の Now In Android サンプルアプリをご覧ください。