AndroidでのGradleについて勉強

## はじめに
Androidの開発を行う際に、`build.gradle`にライブラリを追加することは日常茶飯事だと思います。しかし、ドキュメントに書いてある通りにコピペして、実際の中身についてよくわからずに使っていました。そこで今回、Androidプロジェクトにデフォルトで作成されるGradleファイルについて調べた内容をまとめています。（この文章はChatGPTなどを参照して書いているため、不正確な情報があるかもしれません。ご了承ください。）

## AndroidでのGradle
Android StudioでEmpty Activityを作成すると、次のようなファイル群が作成されます。今回は、`./build.gradle.kts`、`./gradle.properties`、`./settings.gradle.kts`、`./app/build.gradle.kts`のそれぞれについて書いてある内容とその役割を調べました。
``` 
project/
├── app
│   ├── build.gradle.kts
│   ├── proguard-rules.pro
│   └── src
├── build.gradle.kts
├── gradle
│   ├── libs.versions.toml
│   └── wrapper
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle.kts
```

## プロジェクトルートの`build.gradle.kts`
`build.gradle.kts`には実際に使われるプラグインの情報が記述されます。
```kotlin:project/build.gradle.kts
plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.kotlin.android) apply false
}
```

### plugins
プロジェクト内で使用するプラグインを指定
- `id("プラグインID") version "バージョン"`で使うプラグインを指定可能
- `alias`
    - `id`で指定する代わりにcatalog機能を使用したエイリアスによってプラグインIDとバージョンを使うことが可能。catalog内でプロジェクトに使われるプラグインのバージョンを一括管理
    - `~~ apply false`ではプラグインを有効化せずに、他のモジュールや特定の条件においてのみ適用可能。ここでは`android.application`プラグインと`kotlin.android`プラグインの使用することを宣言しているが、`false`となっている

## プロジェクトルートの`settings.gradle.kts`
`settings.gradle.kts`はGradleの設定を定義するファイル。プロジェクトに関連するリポジトリや依存関係の解決方法を指定
```kotlin:project/settings.gradle.kts
pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.name = "My Application"
include(":app")
```
### pluginManagement
プラグインをどこから取得するかの設定
- `google`、`mavenCentral`、`gradlePluginPortal`のリポジトリを指定
- さらに、`google`では`includeGroupByRegex()`でフィルタリングを行っている

### dependencyResolutionManagement
プロジェクトの依存関係解決に関する設定
- `repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)`
    - プロジェクト内で直接かプラグイン経由で宣言されたリポジトリにはエラーを投げる
[doc](https://docs.gradle.org/current/javadoc/org/gradle/api/initialization/resolve/RepositoriesMode.html)
- `repositories {}`
    - 依存関係を解決するためのリポジトリを指定
    - 依存関係とはアプリケーション内で必要な外部ライブラリやモジュール(プラグインはプロジェクト全体のビルドなどの制御に必要なツール)


### その他
- `rootProject.name = "My Application"`
    - ルートプロジェクト名の設定
- `include(":app")`
    - プロジェクトに含めるモジュール
    - モジュールを追加するには、ここにモジュールを追記していく


## プロジェクトルートの`gradle.properties`
`gradle.properties`はビルド時に使用される設定

```kotlin:project/gradle.properties
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
kotlin.code.style=official
android.nonTransitiveRClass=true
```
- `org.gradle.jvmargs`
    - JVMに渡す引数を指定
    - `-Xmx2048m`
        - JVMに割り当てる最大メモリサイズを2048MBに設定
    - '-Dfile.encoding=UTF-8'
        - ファイルエンコーディングをUTF-8に指定
- `android.useAndroidX`
    - AndroidX を使用するかどうかを指定
        - AndroidXは新しいandroidプラットフォームAPIに下位互換性を提供するライブラリ
        - 2018年にSupport Libraryの代替として開発
- `kotlin.code.style`
    - Kotlinのコードスタイル
    - `official`はJetBraninsの推奨コードスタイル
    - `obsolete`でkotlinの初期のコードスタイルが使用可能（非推奨）
    - [Kotlinコードスタイルへの移行](https://kotlinlang.org/docs/code-style-migration-guide.html)
- `android.nonTransitiveRClass`
    - `R`クラス（リソースIDを保持するクラス）の依存関係の伝播を制御する設定
        - `true`:モジュールごとに管理、他モジュールのリソースにアクセスできなくなる
        - デフォルトは`false`で、依存関係のあるモジュール間で`R`クラスが共有される
    - 詳細記事：[【Android】Non-Transitive R Classes を有効にしてビルドを最適化する](https://qiita.com/maxfie1d/items/89450e451a362f951442)


## `app`レベルの`build.gradle.kts`
各モジュールでの設定(長いので`plugin`、`android`、`dependencies`で３分割してます。)
```kotlin:project/app/build.gradle.kts
plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
}
```
### plugins
必要なGradleプラグインを定義
- aliasを利用して`libs.plugins.android.application`と`libs.plugins.kotlin.android`を設定

```kotlin:project/app/build.gradle.kts
android {
    namespace = "com.example.myapplication"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.myapplication"
        minSdk = 33
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary = true
        }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
}
```
### android
Androidアプリのビルド設定

- namespace
    - アプリのパッケージ名を設定
- compileSdk
    - アプリをビルドする際に使用するAndroid APIレベル
    - 34はAndroid 14に対応
    - [SDK Platformリリースノート](https://developer.android.com/tools/releases/platforms?hl=ja)
- defaultConfig
    - アプリのデフォルト設定を定義
    -  `applicationId`：アプリの一意の識別子
    -  `minSdk`：アプリの動作する最低バージョン
    -  `targetSdk`：アプリが最適化されるバージョン
    -  `versionCode`：アプリのビルドバージョン（整数）
    -  `versionName`：アプリのバージョン名（文字列）
        -  `BuildConfig.VERSION_NAME`で利用できる
    -  `testInstrumentationRunner`：インストルメンテーション用のランナーを設定
        - インストルメンテーションテスト：デバイスやエミュレータを利用して行うテスト
        - [インストルメンテーション テストを作成する](https://developer.android.com/training/testing/instrumented-tests?hl=ja)
    -  `vectorDrawables`：ベクターグラフィックス（SVG形式のような画像）のサポート設定
-  buildTypes
    -  ビルドタイプごとの異なる設定(`debug`、`release`など)
    -  `isMinifyEnabled`：コード圧縮の有効化
    -  `proguardFiles`：ProGuardの設定ファイルを指定
        -  ProGuard：難読化や参照されていないコードを削除しくれるツール
- compileOptions
    - javaのソースコードとバイトコードの互換性を設定
- kotlinOptions
    - KotlinのJVMターゲットバージョンを設定
- buildFeatures
    - アプリケーションのビルド時に有効にする特定の機能を設定
    - compose = true: Jetpack Composeの使用を有効化
    - その他にもviewBinding、dataBinding、buildConfig等の機能を有効化可能
- composeOptions
    - Jetpack Compose 用の Kotlin コンパイラ拡張バージョンを指定
- packaging
    - パッケージング時に除外するリソースを指定
    
    
```kotlin:project/app/build.gradle.kts
dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.lifecycle.runtime.ktx)
    implementation(libs.androidx.activity.compose)
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.ui)
    implementation(libs.androidx.ui.graphics)
    implementation(libs.androidx.ui.tooling.preview)
    implementation(libs.androidx.material3)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
    androidTestImplementation(platform(libs.androidx.compose.bom))
    androidTestImplementation(libs.androidx.ui.test.junit4)
    debugImplementation(libs.androidx.ui.tooling)
    debugImplementation(libs.androidx.ui.test.manifest)
}
```
### dependencies
アプリで使用するライブラリの定義
依存関係の種類
- implementation: アプリで使用するライブラリ
- testImplementation: テスト用ライブラリ
- androidTestImplementation: Android テスト用ライブラリ
- debugImplementation: デバッグビルドでのみ使用するライブラリ