AndroidStudioの更新、及びKotlin2.0へのアップデート他

# 目的
`AndroidStudio`を更新するとビルドが通らなくなる場合もあり、しばらく更新していなかったのですが、`Kotlin2.0`へ移行するために、最新版の`Ladybug`へ更新し、ビルドが通るように設定の修正、及びその間に追加された機能への対応を行います。

# 状態
更新前のバージョンは`Android Studio Hedgehog 2023.1.1`、2023年11月にリリースされたので1年少し前の物です。更新後のバージョンは`Android Studio Ladybug 2024.2.1`、2024年10月に正式リリースされました。

# ビルドエラー対応
公式サイトから最新版をダウンロードし、更新しようとしたところ、既存の物が削除されクリーンインストールされました。更新後、既存のプロジェクトを開いたところ、やはりビルドエラーが発生しました。

```
Your build is currently configured to use incompatible Java 21.0.3 and Gradle 8.1.1. Cannot sync the project.

We recommend upgrading to Gradle version 8.9.

The minimum compatible Gradle version is 8.5.

The maximum compatible Gradle JVM version is 19.
```
対応する`Gradle`のバージョンは8.5以上、推奨は8.9とのことなので、`Gradle`をアップデートします。また、対応するJVMは最大でも19までなのに、21が設定されているので、そちらも修正します。

## Gradle のアップデート
`Gradle`をアップデートした際は、`Android Gradle プラグイン`のアップデートが必要な場合があります。`Gradle`と`Android Gradle プラグイン`のバージョン対応表は以下のページで確認できます。
[Gradle のアップデート](https://developer.android.com/build/releases/gradle-plugin?hl=ja#updating-gradle)
```diff_kotlin:gradle-wrapper.properties
- distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
+ distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
```
```diff_kotlin:プロジェクト直下の、build.gradle.kts
plugins {
-    id("com.android.application") version "8.1.1" apply false
-    id("com.android.library") version "8.1.1" apply false
-    id("com.android.dynamic-feature") version "8.1.1" apply false
+    id("com.android.application") version "8.7.3" apply false
+    id("com.android.library") version "8.7.3" apply false
+    id("com.android.dynamic-feature") version "8.7.3" apply false
    // ...
}
```

## JDKの更新
`Menu -> Settings -> Build,Execution,Deployment -> Build Tools -> Gradle` でGradleが参照しているJDKを確認すると、`AndroidStudio`と同時にインストールされたJDKになっており、そちらのバージョンが21.0.3になっています。環境変数`JAVA_HOME`に以前ダウンロードした`OpenJDK17`のパスが設定されていたので、今回はそちらを指定します。

### 設定箇所
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115846/cbbe374f-26ae-e1da-0fe0-b2b2651ee1e8.png)

この時点でビルドが通り、アプリも起動できるようになったので、追加された機能へ対応していきます。

# Kotlinのバージョンアップ
Kotlinを2.0にバージョンアップしようとしたのですが、移行の手順で`version catalogs`が出てきたので一旦後回しにします。

# buildscriptの削除
プラグインを追加する場合、以前は`buildscript`の`dependencies`に記載していましたが、現在は`plugins`へ記載するようになっているので、それに合わせて修正します。
```diff_kotlin:
- buildscript {
-    dependencies {
-        classpath("com.google.gms:google-services:4.4.0")
-        classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.9")
-    }
- }
plugins {
    // ...
+    id("com.google.gms.google-services") version "4.4.0" apply false
+    id("com.google.firebase.crashlytics") version "2.9.9" apply false
}
```


# KSPへの移行
以前はアノテーションプロセッサとして`kapt`が使われていましたが、動作が高速な`KSP`への移行が推奨されています。以下のページを参考に移行します。
[kapt から KSP に移行する &nbsp;|&nbsp; Android Studio &nbsp;|&nbsp; Android Developers](https://developer.android.com/build/migrate-to-ksp)

## Pluginの追加
`KSPプラグイン`のバージョンの先頭部分は、`Kotlin`のバージョンと一致している必要があります。以下のページから対応するプラグインのバージョンを検索し、設定してください。
[Releases · google/ksp · GitHub](https://github.com/google/ksp/releases)
```diff_kotlin:プロジェクト直下の、build.gradle.kts
plugins {
    // ...
    id("org.jetbrains.kotlin.android") version "1.9.24" apply false
+    id("com.google.devtools.ksp") version "1.9.24-1.0.20" apply false
}
```

## アノテーションプロセッサの置き換え
```diff_kotlin:app配下のbuild.gradle.kts
plugins {
    // ...
-    kotlin("kapt")
+    id("com.google.devtools.ksp")
}

dependencies {
// ...
-    kapt("androidx.room:room-compiler:2.6.0")
+    ksp("androidx.room:room-compiler:2.6.0")
// ...
-    kapt("com.google.dagger:hilt-android-compiler:2.47")
+    ksp("com.google.dagger:hilt-android-compiler:2.47")
// ...
-    kapt("androidx.hilt:hilt-compiler:1.0.0")
+    ksp("androidx.hilt:hilt-compiler:1.0.0")
// ...
}
- kapt {
-    correctErrorTypes = true
- }
```

# version catalog対応
プロジェクト直下や、各モジュール毎に存在する`build.gradle.kts`に記載される、プラグインやライブラリのバージョンを一括で管理する仕組みです。`Gradle7.4`で導入され、以前は使用するには設定が必要でしたが、現在はデフォルトで有効になっています。また、最新の`AndroidStudio`でプロジェクトを新規作成すると、`version catalog`に対応した状態でプロジェクトが生成されるため、そちらを参考にしながら作業すると分かりやすいと思います。

[ビルドをバージョン カタログに移行する &nbsp;|&nbsp; Android Studio &nbsp;|&nbsp; Android Developers](https://developer.android.com/build/migrate-to-catalogs)
[Version Catalogs](https://docs.gradle.org/current/userguide/version_catalogs.html)

## 設定ファイルの作成
プロジェクト直下の`gradle`フォルダに`libs.versions.toml`の名前でファイルを作成し、以下の3つのカテゴリを追加します。バージョンに使用する定数を`[versions]`に、モジュール配下の`build.gradle.kts`の`dependencies`で使用する定数を`[libraries]`に、プロジェクト直下の`build.gradle.kts`の`plugins`で使用する定数を`[plugins]`に定義します。

```diff_kotlin:libs.versions.toml
+ [versions]
+
+ [libraries]
+
+ [plugins]
+
```


## プラグインの設定
`[versions]`にバージョンの定数を定義し、`[plugins]`に`id`と`version.ref`を指定した定数を定義します。単語の区切り文字にはハイフン`[-]`を使うことが推奨されています。

```diff_kotlin:libs.versions.toml
[versions]
+ agp = "8.7.3"
+ kotlin = "1.9.24"
+ ksp = "1.9.24-1.0.20"

[libraries]

[plugins]
+ android-application = { id = "com.android.application", version.ref = "agp" }
+ android-library = { id = "com.android.library", version.ref = "agp" }
+ android-dynamic-feature = { id = "com.android.dynamic-feature", version.ref = "agp" }

+ kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin"}
+ devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp"}
```
`libs.versions.toml`で定義した定数を使って、`alias`でプラグインを設定します。
```diff_kotlin:プロジェクト直下の、build.gradle.kts
plugins {
-    id("com.android.application") version "8.7.3" apply false
-    id("com.android.library") version "8.7.3" apply false
-    id("com.android.dynamic-feature") version "8.7.3" apply false
+    alias(libs.plugins.android.application) apply false
+    alias(libs.plugins.android.library) apply false
+    alias(libs.plugins.android.dynamic.feature) apply false

-    id("org.jetbrains.kotlin.android") version "1.9.24" apply false
-    id("com.google.devtools.ksp") version "1.9.24-1.0.20" apply false
+    alias(libs.plugins.kotlin.android) apply false
+    alias(libs.plugins.devtools.ksp) apply false
}
```
## ライブラリの設定
プラグインの設定とほぼ同じですが、`group`、`name`、`version.ref`を使います。
```diff_kotlin:libs.versions.toml
[versions]
+ coreKtx = "1.9.0"
+ lifecycle = "2.6.1"
+ composeBom = "2023.10.01"

[libraries]
+ androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }

+ androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" }
+ androidx-lifecycle-common = { group = "androidx.lifecycle", name = "lifecycle-common", version.ref = "lifecycle" }
+ androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" }
+ androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" }

+ androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
+ androidx-ui = { group = "androidx.compose.ui", name = "ui" }
+ androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
+ androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
```
`version catalog`を使わない時と同様に、`implementation`を使って設定します。`bom`を使った設定も可能です。
```diff_kotlin:app配下のbuild.gradle.kts
plugins {
-    id("com.android.application")
-    id("org.jetbrains.kotlin.android")
-    id("com.google.devtools.ksp")
+    alias(libs.plugins.android.application)
+    alias(libs.plugins.kotlin.android)
+    alias(libs.plugins.devtools.ksp)
    // ...
}

dependencies {
-    implementation("androidx.core:core-ktx:1.9.0")
+    implementation(libs.androidx.core.ktx)

-    val lifecycleVersion = "2.6.1"
-    implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion")
-    implementation("androidx.lifecycle:lifecycle-common:$lifecycleVersion")
-    implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycleVersion")
-    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion")
+    implementation(libs.androidx.lifecycle.runtime.ktx)
+    implementation(libs.androidx.lifecycle.common)
+    implementation(libs.androidx.lifecycle.runtime.compose)
+    implementation(libs.androidx.lifecycle.viewmodel.compose)

-    implementation(platform("androidx.compose:compose-bom:2023.10.01"))
-    implementation("androidx.compose.ui:ui")
-    implementation("androidx.compose.ui:ui-graphics")
-    implementation("androidx.compose.material3:material3")
+    implementation(platform(libs.androidx.compose.bom))
+    implementation(libs.androidx.ui)
+    implementation(libs.androidx.ui.graphics)
+    implementation(libs.androidx.material3)
    // ...
}
```

# Kotlinのバージョンアップ
以前は`Kotlin`のバージョンに対応する`Compose Compiler`のバージョンを指定する必要がありましたが、`Kotlin2.0`からは、`Compose Compiler Gradle プラグイン`を使用するようになり、バージョンも`Kotlin`と同一の物を使用するようになりました。

## 設定の変更
`Kotlin`のバージョンを変更し、`KSP`のバージョンも対応する物に変更します。`Compose Compiler Gradle プラグイン`の定数を定義します。

```diff_kotlin:libs.versions.toml
[versions]
- kotlin = "1.9.24"
- ksp = "1.9.24-1.0.20"
+ kotlin = "2.0.0"
+ ksp = "2.0.0-1.0.24"

[plugins]
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin"}
+ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp"}
```
`Compose Compiler Gradle プラグイン`の設定を追加し、既存の`Compose Compiler`の設定を削除します。
```diff_kotlin:プロジェクト直下の、build.gradle.kts
plugins {
    // ...
    alias(libs.plugins.kotlin.android) apply false
+    alias(libs.plugins.compose.compiler) apply false
    alias(libs.plugins.devtools.ksp) apply false
    // ...
```

```diff_kotlin:app配下のbuild.gradle.kts
plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
+    alias(libs.plugins.compose.compiler)
    alias(libs.plugins.devtools.ksp)
    // ...
-    composeOptions {
-        kotlinCompilerExtensionVersion = "1.5.14"
-    }
}
```
`Sync Project with Gradle Files`後、`Make Module`を行ったところ、無事ビルドが成功しました。`Kotlin`のバージョンを出力するようにして確認します。

```kotlin
Log.d("MainApplication", "${KotlinVersion.CURRENT}")
```
```
2025-01-07 20:29:29.755  6881-6881  MainApplication  ...   D  2.0.0
```

無事`Kotlin2.0`へのアップデートが完了しました。