Contents
開発環境の準備 ― Android Studio Flamingo と OpenJDK 17 のインストール・設定
📌 目的
Kotlin/Jetpack Compose を用いた Android アプリ開発をスムーズに開始できるよう、Android Studio Flamingo (2024.1) と OpenJDK 17 を正しく導入し、IDE と JDK のバージョンが一致していることを確認します。
✅ 必要条件
| 項目 | 推奨バージョン |
|---|---|
| Android Studio | Flamingo (2024.1) 以上 |
| JDK | OpenJDK 17(Android Studio に同梱) |
| OS | Windows 10/11、macOS 13+、Linux (Ubuntu 22.04 推奨) |
手順詳細
| 手順 | 操作内容 |
|---|---|
| 1 | Android Studio の公式ページ https://developer.android.com/studio にアクセスし、Download Options → Windows/macOS/Linux → Flamingo を選択してインストーラを取得。 |
| 2 | ダウンロードしたインストーラを実行。 ・「JDK を自動的に設定する」に必ずチェックが入っていることを確認(デフォルトで OpenJDK 17 がバンドルされています)。 |
| 3 | インストール完了後、File ► Settings (macOS は Preferences) → Appearance & Behavior ► System Settings ► Android SDK に移動し、SDK Tools タブで以下にチェックを入れる。 ・Android SDK ・Android Emulator ・Google Play services |
| 4 | 環境変数 JAVA_HOME が JDK の実体ディレクトリを指すか確認する(Windows は C:\Program Files\Android\Android Studio\jre、macOS は /Applications/Android Studio.app/Contents/jbr)。ターミナル/コマンドプロンプトで java -version と入力し、openjdk version "17" が表示されれば成功。 |
| 5 | Android Studio を再起動し、Help ► About で「Android Studio Flamingo」および「JDK 17」と表示されていることを最終確認する。 |
ポイント
IDE と JDK のバージョンが食い違うと、Kotlin 1.9 系のコンパイルエラーや Gradle 8 との非互換が頻発します。上記チェックリストで必ず「一致」を確認してください。
公式 Codelab ― Kotlin と Jetpack Compose のハンズオン
📚 概要
Google が提供する 2024 年版 Codelab は、Kotlin 基礎 → Compose 初体験 → 完成アプリまでを段階的に学べる教材です。2 つのラボ(「初めての Kotlin プログラム」・「初めての Android アプリを作成する」)を順番に実施すれば、Hello World が画面に表示されるアプリ が手元で完成します。
手順
- Kotlin 基礎ラボ
- URL: https://developer.android.com/codelabs/basic-android-kotlin-compose-first-app?hl=ja
- 左メニューの Kotlin Basics を選択し、画面右上の Run on Android Studio ボタンをクリック。自動で
HelloWorld.ktが生成されます。 -
ファイル内の
fun main()にprintln("Hello, Kotlin!")と記述し、IDE の緑色再生ボタンで実行。コンソールに文字列が出力されたら成功です。 -
Compose 初体験ラボ
- 同ページの Compose First App セクションへスクロールし、Open in Android Studio をクリック。
Empty Compose Activityテンプレートが含まれたプロジェクトがダウンロードされます。 -
MainActivity.ktのデフォルトコードは次の通りです。kotlin
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { Greeting("Compose") }
}
}
-
エミュレータまたは実機で Run ► app を選択し、画面に「Hello Compose!」が表示されれば完了です。
よくあるエラーと対処
| エラーメッセージ | 原因例 | 解決策 |
|---|---|---|
| Gradle sync failed | Gradle Wrapper が無効、またはネットワーク遮断 | File ► Settings ► Build, Execution, Deployment ► Gradle → “Use default gradle wrapper” を有効化し、プロキシ設定や VPN の有無を確認 |
| Failed to resolve: androidx.compose… | SDK コンポーネントが不足 | SDK Manager ► SDK Tools で「Android Compose UI」や「Jetpack Compose Compiler」を最新版に更新 |
| JAVA_HOME points to a JRE, not a JDK | 環境変数が JRE ディレクトリを指す | JAVA_HOME を JDK(OpenJDK 17)へ再設定し、ターミナルで java -version が正しく表示されるか確認 |
Kotlin 基礎文法と Android Studio のコード補完活用術
🔑 必須構文
| 構文 | 説明・サンプル |
|---|---|
val / var |
変更不可/可変の変数宣言。val title = "Android"、var count = 0 |
when |
複数分岐を式として書ける。kotlin<br>when (state) {<br> State.Loading -> showLoading()<br> State.Success -> showContent(data)<br> else -> showError()<br>}<br> |
| 関数定義 | パラメータと戻り値の型を明示。fun greet(name: String): String = "Hello, $name!" |
データクラス (data class) |
UI 状態や API 返却オブジェクトに最適。data class User(val id: Int, val name: String) |
Android Studio の補完機能
| 機能 | キーショートカット / 操作方法 |
|---|---|
| Live Templates(ライブテンプレート) | @Composable と入力 → Tab で fun MyScreen() {} が生成。設定は File ► Settings ► Editor ► Live Templates |
Smart Completion (Ctrl+Shift+Space) |
型が期待される位置で候補を絞り込み、mutableStateOf("") 等の Compose 用関数を即挿入 |
| Import Optimizer | Alt+Enter で未インポートクラスを自動追加。不要な import は Code ► Optimize Imports または保存時に自動削除 |
| Code Inspection | 未使用変数や Null 安全性の警告がリアルタイムで表示され、Alt+Enter ですぐに修正可能 |
ポイント
補完機能をフル活用すれば、手入力ミスが激減し、Compose の宣言的 UI を高速に記述できます。
プロジェクト作成とパッケージ構成のベストプラクティス
📂 推奨ディレクトリ構造(Feature‑by‑Feature アプローチ)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
com.example.myfirstcomposeapp │ ├─ ui // 画面単位、Composable 関数だけを置く │ ├─ home │ │ └─ HomeScreen.kt │ └─ common // 再利用可能 UI コンポーネント │ └─ CustomButton.kt │ ├─ viewmodel // AndroidX ViewModel クラス │ └─ MainViewModel.kt │ ├─ data // リポジトリ・ドメインモデル │ ├─ repository │ │ └─ UserRepository.kt │ └─ model │ └─ User.kt │ └─ di // Hilt/Dagger の依存性注入設定(任意) └─ AppModule.kt |
作成手順
- テンプレート選択
- Android Studio → New Project → Empty Compose Activity。
-
言語は Kotlin、最低 API は 26 (Android 8.0) を推奨。プロジェクト名は
MyFirstComposeAppとし、保存先を指定して Finish。 -
パッケージ作成
-
プロジェクトビューで app > java 配下に上記構造のフォルダを手動で追加(右クリック → New → Package)。
-
依存関係の整理 (
build.gradle.kts例)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
plugins { id("com.android.application") kotlin("android") id("dagger.hilt.android.plugin") version "2.48" } android { compileSdk = 34 defaultConfig { applicationId = "com.example.myfirstcomposeapp" minSdk = 26 targetSdk = 34 versionCode = 1 versionName = "1.0" } buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.5.3" } } dependencies { implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.activity:activity-compose:1.8.2") implementation("androidx.compose.ui:ui:1.5.4") implementation("androidx.compose.material3:material3:1.2.0") // Hilt implementation("com.google.dagger:hilt-android:2.48") kapt("com.google.dagger:hilt-compiler:2.48") } |
ポイント
フィーチャごとにパッケージを分割すると、コード検索やレビューがスムーズになるだけでなく、将来的なモジュール化(Dynamic Feature Modules)にも対応しやすくなります。
UI 実装と状態管理 ― Compose と ViewModel の連携
📌 基本コンポーネント例
| コンポーネント | 主な用途 |
|---|---|
Button |
ユーザー操作のトリガー |
Text |
静的・動的文字列表示 |
TextField |
テキスト入力 |
Image |
画像描画(painterResource / rememberImagePainter) |
完全サンプルコード
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
// --------------------------------------------------- // data/GreetingUiState.kt // --------------------------------------------------- package com.example.myfirstcomposeapp.data data class GreetingUiState( val name: String = "", val greeting: String = "" ) // --------------------------------------------------- // viewmodel/MainViewModel.kt // --------------------------------------------------- package com.example.myfirstcomposeapp.viewmodel import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import com.example.myfirstcomposeapp.data.GreetingUiState class MainViewModel : ViewModel() { private val _uiState = mutableStateOf(GreetingUiState()) val uiState: State<GreetingUiState> = _uiState fun onNameChange(newName: String) { _uiState.value = _uiState.value.copy(name = newName) } fun generateGreeting() { val message = "Hello, ${_uiState.value.name}!" _uiState.value = _uiState.value.copy(greeting = message) } } // --------------------------------------------------- // ui/home/HomeScreen.kt // --------------------------------------------------- package com.example.myfirstcomposeapp.ui.home import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.example.myfirstcomposeapp.viewmodel.MainViewModel @Composable fun HomeScreen(viewModel: MainViewModel = viewModel()) { val state by viewModel.uiState Column( modifier = Modifier .fillMaxSize() .padding(16.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.Start ) { Text( text = "Kotlin Android アプリ開発 デモ", style = MaterialTheme.typography.headlineSmall ) Spacer(modifier = Modifier.height(12.dp)) TextField( value = state.name, onValueChange = { viewModel.onNameChange(it) }, label = { Text("名前を入力") }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(8.dp)) Button( onClick = { viewModel.generateGreeting() }, modifier = Modifier.align(Alignment.End) ) { Text("挨拶する") } Spacer(modifier = Modifier.height(12.dp)) if (state.greeting.isNotEmpty()) { Text( text = state.greeting, style = MaterialTheme.typography.bodyLarge ) } } } |
ポイント解説
| 項目 | 内容 |
|---|---|
| 状態保持 | mutableStateOf を ViewModel 内で使用し、画面回転やプロセス再生成時もデータが失われないようにしています。 |
| UI の再描画 | val state by viewModel.uiState と by デリゲートを使うことで、状態が変化した瞬間に Compose が自動的に再コンポーズします。 |
| 依存性注入(任意) | 大規模プロジェクトでは Hilt による @HiltViewModel アノテーションで ViewModel の生成を委譲すると、テストが容易になります。 |
ビルド・リリースフローと基本メンテナンス
1️⃣ デバッグビルドの実行
| 手順 | 操作 |
|---|---|
| エミュレータ起動 | Android Studio の AVD Manager → 「Pixel 5 API 33」→ Launch |
| Run | 緑色再生ボタンでデバッグビルド(assembleDebug)を実行。Logcat では TAG: "MyApp" 等でフィルタリングすると見やすいです。 |
| 実機テスト | デバイス側で 設定 → 開発者向けオプション → USB デバッグ を有効にし、adb devices で認識を確認後、同様に Run |
2️⃣ リリースビルド(AAB)作成手順
|
1 2 3 4 |
# プロジェクトのルートで実行 ./gradlew clean assembleRelease # APK (デバッグ用以外は基本的に不要) ./gradlew bundleRelease # AAB を生成 |
署名設定例(app/build.gradle.kts)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
android { signingConfigs { create("release") { // keystore のパスはプロジェクトルートからの相対パスで OK storeFile = file("../keystore/release.jks") // 環境変数から取得し、コードに平文を書かないようにする storePassword = System.getenv("KEYSTORE_PASSWORD") keyAlias = "my_key" keyPassword = System.getenv("KEY_PASSWORD") } } buildTypes { getByName("release") { signingConfig = signingConfigs.getByName("release") isMinifyEnabled = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } } |
セキュリティ注意
gradle.propertiesに平文でパスワードを書かないこと。CI 環境では GitHub Secrets などから環境変数を注入します。
3️⃣ Google Play Console へのアップロード
- Play Console にログイン → アプリ > リリース管理 > プロダクション → 新しいリリースを作成
app-release.aabをドラッグ&ドロップでアップロード。自動的に署名検証が走ります。- 必要なメタ情報(タイトル、説明文、スクリーンショット)を入力し、審査依頼 を送信。
4️⃣ CI/CD と品質管理
| 作業 | 推奨ツール |
|---|---|
| ソースコード管理 | Git + GitHub (ブランチ戦略は main/develop/feature/*) |
| 自動ビルド・テスト | GitHub Actions(./gradlew test && ./gradlew bundleRelease) |
| クラッシュレポート | Firebase Crashlytics (implementation "com.google.firebase:firebase-crashlytics") |
| アナリティクス | Google Analytics for Firebase |
GitHub Actions のサンプルワークフロー(.github/workflows/release.yml)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
name: Build & Release on: push: tags: - 'v*' # v1.0, v2.3 などのタグが付いたとき実行 jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' - name: Gradle Wrapper Validation run: ./gradlew --version - name: Build Release AAB env: KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} run: | ./gradlew clean bundleRelease - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: app-release-aab path: app/build/outputs/bundle/release/app-release.aab |
次のステップ ― サンプルプロジェクトをクローンして公開
手順まとめ
-
リポジトリの取得
bash
git clone https://github.com/example/first-compose-sample.git
cd first-compose-sample -
Android Studio でオープン
-
File ► Open → プロジェクトディレクトリを選択。Gradle が自動同期され、
build.gradle.ktsの依存関係が解決されます。 -
ビルド・実行
-
エミュレータまたは USB 接続した端末で Run →
appを選択し、先ほど作成した Greeting UI が起動すれば成功です。 -
自分のリポジトリへフォーク & プッシュ
bash
git remote rename origin upstream # オリジナルを upstream に変更
git remote add origin https://github.com/<your-username>/my-first-compose-app.git
git push -u origin main
- README とデモ動画の追加
README.mdに「プロジェクト概要」「ビルド手順」「ライセンス(MIT 推奨)」を記載。- デモは GitHub Pages か YouTube の非公開リンクで添付すると、ポートフォリオとして評価が上がります。
最終的なポイント
「環境構築 → Codelab 実施 → 基礎文法習得 → プロジェクト設計 → UI と状態管理 → ビルド・リリース」 の流れをすべて体験できれば、Kotlin Android アプリ開発の全体像が把握できます。次は 「高度な Compose パターン(LazyColumn, Navigation, Animation)」 に挑戦しましょう。
この記事は 2024 年版 Android Studio Flamingo と最新 Kotlin/Compose 環境を前提に執筆しています。OS や IDE のバージョンが変わった場合は、公式ドキュメントで対応状況をご確認ください。