Kotlin Multiplatform と Compose Multiplatform を利用して iOS、Androidアプリを爆速で作ってみた。

はじめに

こんにちは!アソビューのバックエンドエンジニアのけんすーです。
先月まで Android 開発に携わっていましたが、チーム移動があり Android のコードに触れる機会が減ってしまいました。Jetpack Compose の記憶も薄れつつあります…。
そこで、リハビリも兼ねて個人的に注目している Kotlin Multiplatform と Compose Multiplatform を試してみることにしました。

この記事では、実際に Kotlin Multiplatform + Compose Multiplatform を使って iOS / Android アプリを作成し、使用感や開発体験についてお伝えします。

作成したアプリは以下の GitHub リポジトリから確認できます。

github.com

Kotlin Multiplatform とは

Kotlin Multiplatform は、Kotlin を用いてクロスプラットフォーム開発を可能にする環境です。 iOS、Android、デスクトップ、Web アプリケーションといった複数プラットフォームでコードを共通化でき、開発効率の向上やメンテナンス負担の軽減が期待されています。

以下のような特徴が挙げられます。

  • ビジネスロジックの共通化
    Kotlin Multiplatform を利用することで、API 呼び出しやデータ処理、状態管理などをプラットフォーム間で共有可能です。異なるプラットフォームでの実装の重複の削減できます。

  • ネイティブコードの組み込み
    必要に応じて、iOS や Android 固有のコードを Kotlin Multiplatform 内にシームレスに統合できます。例えば、位置情報取得やデバイス操作などのネイティブ機能にも対応可能です。

  • 段階的な導入
    新規プロジェクトへの適用だけでなく、既存プロジェクトの一部に Kotlin Multiplatform を導入することで、移行リスクを最小限に抑えながら開発を進めることができます。

モバイル開発では、プラットフォーム間のコード共有による効率化と、メンテナンスコスト削減が期待されています。

Compose Multiplatform とは

Compose Multiplatform は、Jetpack Compose をベースにした宣言的 UI フレームワークで、複数のプラットフォームで同一の UI を構築できます。
Kotlin Multiplatform と組み合わせることで、ロジックだけでなく UI も共通化できるようになりました。

以前は、Kotlin Multiplatform を利用してロジックを共通化しても、UI は各プラットフォームごとにネイティブコードで実装する必要がありました。
Android では Jetpack Compose、iOS では UIKit や SwiftUI を使用するケースが一般的でしたが、これにより UI 実装のコストが高くなる課題がありました。

Compose Multiplatform を利用することで、以下のようなメリットが得られます。

  • フル Kotlin 化
    ロジックから UI までを Kotlin で記述できるため、開発者の学習コストを低減し、開発速度を向上させます。

  • デザインと動作の一貫性
    1 つのコードベースで複数プラットフォームに対応可能なため、異なるプラットフォーム間でも統一された UI と動作を実現できます。

  • 開発効率の向上
    プラットフォームごとの実装を統一することで、テスト工数やコードレビューの効率化にもつながります。

ただし、Compose Multiplatform はまだ発展途上のプロジェクトです。iOS のサポートはbeta版、Web のサポートはalpha版です。実際の開発においては最新のドキュメントやサンプルコードを参照しながら進めることをお勧めします。

Compose Multiplatform UI フレームワーク | JetBrains

事前準備

動作環境

  • macOS Sonoma 14.6.1
  • Android Studio Ladybug 2024.2.1 Patch 2
  • Xcode 15.2.0

セットアップ

Android、iOS の開発環境が整備されていることを前提としています。
各プラットフォームのセットアップについてはJetBrainsの公式ドキュメントが参考になります。
Set up an environment | Kotlin Multiplatform Development Documentation

Kotlin Multiplatform のセットアップが正しくできているかは、 Kdoctor というツールで確認できます。

Homebrew 経由で kdoctor をインストールします。

brew install kdoctor

コマンドを実行すると、以下のようなメッセージが表示されます。
すべてチェックマークがつけばセットアップ完了です。

kdoctor
Environment diagnose (to see all details, use -v option):
[✓] Operation System
[✓] Java
[✓] Android Studio
[✓] Xcode
[✓] CocoaPods

Conclusion:
  ✓ Your operation system is ready for Kotlin Multiplatform Mobile Development!

プロジェクトの作成

Android Studio には新規プロジェクトウィザードがありますが、現時点ではネイティブ UI コードが使用され、Jetpack Compose は使用されません。 代わりに JetBrains のオンラインプロジェクトウィザードを利用します。

ウィザード

今回は iOS, Android にチェックし、UI も共有するため Share UI を選択してダウンロードします。
zip解凍後、Android Studio でプロジェクトルートを開いて同期します。

構造

Android ではなく Project ビューを選択すると全体構造を確認できます。

Compose Multiplatform を使用したプロジェクトでは、以下のようなディレクトリ構造を持ちます。

  • composeApp
    • プロジェクトのメインコードが格納されているフォルダです。
    • src フォルダ内には、共通コード用の commonMain、プラットフォーム固有コード用の androidMainiosMain が含まれます。
      • commonMain: すべてのプラットフォームで共有されるコードを定義します。
      • androidMain: Android 固有のコードを定義します。
        • 例: MainActivity.kt
      • iosMain: iOS 固有のコードを定義します。
        • 例: MainViewController.kt
    • build.gradle.kts ファイルには、Compose や依存ライブラリを管理する設定が記述されています。
  • iosApp
    • iOS アプリをビルドするための Xcode プロジェクトを格納します。
    • iosApp.xcodeprojInfo.plistiOSApp.swift が含まれます。
  • プロジェクト全体
    • ルートには settings.gradle.ktsgradle.properties などのプロジェクト設定ファイルが含まれています。

起動

作成したプロジェクトで Android アプリと iOS アプリを起動します。それぞれのプラットフォームでの起動方法を簡単に解説します。

Android アプリの起動

  1. Run > Run 'composeApp' を選択
  2. 任意のエミュレーターを選択し起動します。

エミュレーターの追加方法は公式ドキュメントをご参照ください。

iOS アプリの起動

  1. Xcode を起動しておきます。
  2. Android Studio の実行の構成を追加します。
    1. Android Studio のメニューから Run > Edit Configurations を選択します。
    2. 新規構成を追加するために + をクリックし、iOS Application を選択します。
    3. 以下の情報を入力します。
      • Name: 任意の名称(例: iosApp
      • Xcode project file: /プロジェクトルート/iosApp/iosApp.xcodeproj
      • Xcode project schema: iosApp
      • Xcode project configuration: Debug または Release
      • Execution target: 任意の iOS バージョン
  3. 追加した実行構成でアプリを起動します。

以下は、Android アプリと iOS アプリを起動した際の画面のスクリーンショットです。

コード追加

初回起動時に表示される画面は、composeApp/src/commonMain/kotlin/org/example/project/App.kt で実装されています。 このファイルは、Compose Multiplatform プロジェクトで共通 UI を管理するエントリーポイントになっています。

初期のコードでは、ボタンをクリックすると画像とテキストが表示されるシンプルな UI が実装されています。
今回はそのコードを少し変更し、ボタンをクリックするとダイアログが表示されるようにしてみます。

変更点

@Composable
@Preview
fun App() {
    MaterialTheme {
        var showContent by remember { mutableStateOf(false) }
        Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
            Button(onClick = { showContent = !showContent }) {
                Text("Click me!")
            }
            AnimatedVisibility(showContent) {
                val greeting = remember { Greeting().greet() }
-                Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
-                    Image(painterResource(Res.drawable.compose_multiplatform), null)
-                    Text("Compose: $greeting")
+                AlertDialog(
+                    onDismissRequest = { showContent = false },
+                    title = {
+                        Row(verticalAlignment = Alignment.CenterVertically) {
+                            Icon(Icons.Default.Info, contentDescription = null)
+                            Spacer(modifier = Modifier.width(8.dp))
+                            Text("ダイアログ")
+                        }
+                    },
+                    text = {
+                        Text(greeting)
+                    },
+                    confirmButton = {
+                        Button(onClick = { showContent = false }) {
+                            Text("OK")
+                        }
+                    },
+                    backgroundColor = MaterialTheme.colors.surface,
+                    shape = MaterialTheme.shapes.medium
+                )
            }
        }
    }
}

実行結果

Jetpack Compose のコードを使って、iOS と Android の両方で同じ UI を実現できました!

まとめ

Compose Multiplatform を使うことで、慣れ親しんだ Jetpack Compose をそのまま活用して、同じ UI の iOS アプリを作成できました。iOS アプリ開発の経験がほとんどない私でも、Jetpack Compose の知識さえあれば、スピード感を持って開発を進められることを実感しました。

ただし、Compose Multiplatform はまだ試験的な段階であり、安定性や実用性には注意が必要です。また、周辺ライブラリも発展途上であり、日本語の情報が少ない点も課題の一つです。

今後、Compose Multiplatform が成熟し、エコシステムが充実してくれば、より多くの開発者がそのメリットを享受できるようになるでしょう。引き続き最新情報を注視しつつ、今後のアップデートに期待したいと思います!

さいごに

アソビューでは、一緒に働くメンバーを大募集しています!カジュアル面談も実施しておりますので、少しでもご興味をお持ちいただけましたら、ぜひお気軽にご応募ください!

www.asoview.com