Kotlin Multiplatformのセットアップ方法を徹底解説!効率的にクロスプラットフォーム開発を始める手順

Kotlin Multiplatformは、モバイル、デスクトップ、Webといった複数のプラットフォーム向けに、コードを効率よく共有しながら開発できる画期的な技術です。特に、AndroidとiOS向けにアプリを同時に開発したい場合、共通コードを一つにまとめ、プラットフォーム固有の部分だけを個別に実装することで、時間とコストを大幅に削減できます。

本記事では、Kotlin Multiplatformを初めて導入する方に向けて、セットアップ手順をわかりやすく解説します。開発環境の準備から、Gradle設定、コード共有、デバッグ方法、さらには実際のアプリの作成例まで詳しく紹介します。Kotlin Multiplatformを使えば、クロスプラットフォーム開発がシンプルかつ効率的に行えます。

目次

Kotlin Multiplatformとは何か


Kotlin Multiplatform(KMP)とは、JetBrainsが開発したKotlin言語を使って、複数のプラットフォーム向けにコードを共有しながらアプリケーションを開発できる仕組みです。特にAndroid、iOS、デスクトップ、Webといった異なるプラットフォームに対応しており、共通ビジネスロジックやデータ処理ロジックを一度書けば、各プラットフォームに再利用できます。

Kotlin Multiplatformの特徴

  1. コードの再利用性
    共通部分を一度書けば、複数のプラットフォームで利用できるため、開発時間を短縮できます。
  2. プラットフォーム固有コードの柔軟なサポート
    UIやOS固有の機能が必要な場合は、プラットフォームごとにカスタム実装が可能です。
  3. ネイティブパフォーマンス
    各プラットフォーム向けにネイティブコードが生成されるため、パフォーマンスの低下がありません。
  4. AndroidとiOSのサポート
    Android開発者にもiOS開発者にも馴染みやすい仕組みで、双方の開発スキルを活かせます。

Kotlin Multiplatformの利用シーン

  • モバイルアプリ開発: AndroidとiOSアプリを同時に開発。
  • Webとデスクトップの統合: 同じロジックでWebアプリやデスクトップアプリを作成。
  • ライブラリ開発: 複数プラットフォーム向けの共通ライブラリやSDKを開発。

Kotlin Multiplatformを活用することで、開発リソースを効率化し、メンテナンスしやすいプロジェクト構成を実現できます。

開発環境の準備


Kotlin Multiplatformプロジェクトを始めるには、まず開発環境を適切に準備する必要があります。以下に、必要なツールと設定手順を説明します。

必要なツールのインストール

  1. IntelliJ IDEAまたはAndroid Studio
  • IntelliJ IDEA: Ultimate Editionが推奨されます。
  • Android Studio: Android開発に特化しています。 これらのIDEは、Kotlin Multiplatformのサポートが組み込まれています。
  1. JDKのインストール
  • JDK 11以上が必要です。
  • AdoptOpenJDKなどからダウンロードしてインストールします。
  1. Xcode(iOS開発の場合)
  • iOS向けのビルドにはXcodeが必須です。
  • Mac上でApp Storeからインストールできます。

プロジェクトの作成

  1. 新規プロジェクトの作成
  • IntelliJ IDEAまたはAndroid Studioを開き、「New Project」を選択します。
  • 「Kotlin Multiplatform」テンプレートを選択し、必要なプラットフォーム(Android、iOS、Desktopなど)を指定します。
  1. 依存関係の設定
    プロジェクト作成後、build.gradle.ktsに必要な依存関係を追加します。例えば:
   kotlin {
       android()
       iosX64()
       iosArm64()

       sourceSets {
           val commonMain by getting {
               dependencies {
                   implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2")
               }
           }
           val androidMain by getting
           val iosMain by getting
       }
   }

Android SDKとiOSシミュレータの確認

  • Android SDKが正しく設定されていることを確認します。
  • iOS開発では、Xcodeのシミュレータまたは実機が使用可能であることを確認します。

これで、Kotlin Multiplatformの開発環境が整いました。次は、Gradle設定とプロジェクト構成について見ていきます。

Gradle設定とプロジェクト構成


Kotlin Multiplatformプロジェクトを効率的に管理するためには、Gradleを使った適切な設定とディレクトリ構成が重要です。以下に、基本的なGradle設定とプロジェクト構成について解説します。

Gradle設定ファイルの概要


Kotlin Multiplatformプロジェクトでは、主に以下のGradleファイルを設定します。

  • build.gradle.kts(ルート): プロジェクト全体の設定。
  • build.gradle.kts(モジュールごと): 各モジュールのビルド設定。
  • settings.gradle.kts: モジュールの登録やリポジトリの設定。

基本的な`build.gradle.kts`設定


以下は、Kotlin Multiplatformプロジェクトにおけるbuild.gradle.ktsのサンプルです。

plugins {
    kotlin("multiplatform") version "1.9.0"
}

kotlin {
    // ターゲットプラットフォームを指定
    android()
    iosX64()
    iosArm64()

    // ソースセットの設定
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2")
            }
        }
        val androidMain by getting
        val iosMain by getting
    }
}

android {
    compileSdkVersion(34)
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
}

プロジェクトのディレクトリ構成


Kotlin Multiplatformプロジェクトでは、共通コードとプラットフォーム固有コードを以下のように整理します。

MyKMPProject/
│-- build.gradle.kts
│-- settings.gradle.kts
│-- gradle/
│-- shared/
│   │-- src/
│   │   │-- commonMain/
│   │   │   └── kotlin/
│   │   │       └── CommonCode.kt
│   │   │-- androidMain/
│   │   │   └── kotlin/
│   │   │       └── AndroidCode.kt
│   │   │-- iosMain/
│   │       └── kotlin/
│   │           └── IOSCode.kt
│-- androidApp/
│   │-- build.gradle.kts
│   └── src/main/
│       └── AndroidManifest.xml
└-- iosApp/
    └── iOSプロジェクトファイル

ターゲットプラットフォームの追加


プロジェクトに新しいプラットフォームを追加する場合、kotlin {}ブロックにターゲットを追加します。

例: デスクトップ向けターゲットの追加

kotlin {
    jvm("desktop")
}

依存関係の管理


各プラットフォームに必要なライブラリをsourceSetsごとに追加します。

sourceSets {
    val androidMain by getting {
        dependencies {
            implementation("androidx.core:core-ktx:1.9.0")
        }
    }
    val iosMain by getting {
        dependencies {
            implementation("io.ktor:ktor-client-ios:2.0.0")
        }
    }
}

これでGradle設定とプロジェクト構成の基本が整いました。次は、iOS・Android向けのコード共有方法を見ていきます。

iOS・Android向けのコード共有方法


Kotlin Multiplatformでは、共通ビジネスロジックを共有しながら、プラットフォーム固有の機能やUI部分を個別に実装できます。ここでは、iOSとAndroid向けにコードを共有する基本的な方法を解説します。

共通コードの作成


共通コードは、commonMainソースセット内に配置します。ビジネスロジック、データ処理、ネットワーク通信といった部分をここに書きます。

例: shared/src/commonMain/kotlin/PlatformGreeting.kt

package com.example.shared

class PlatformGreeting {
    fun greet(): String = "Hello from Kotlin Multiplatform!"
}

Android固有のコード


Android固有の機能は、androidMainソースセット内に記述します。例えば、AndroidのToastメッセージを表示する関数を作成します。

例: shared/src/androidMain/kotlin/AndroidGreeting.kt

package com.example.shared

import android.content.Context
import android.widget.Toast

actual class PlatformGreeting(val context: Context) {
    actual fun greet() {
        Toast.makeText(context, "Hello from Android!", Toast.LENGTH_SHORT).show()
    }
}

iOS固有のコード


iOS固有の機能は、iosMainソースセット内に記述します。例えば、iOSでアラートを表示する関数を作成します。

例: shared/src/iosMain/kotlin/IOSGreeting.kt

package com.example.shared

import platform.UIKit.UIAlertController
import platform.UIKit.UIApplication
import platform.UIKit.UIWindow
import platform.UIKit.presentViewController

actual class PlatformGreeting {
    actual fun greet() {
        val alert = UIAlertController.alertControllerWithTitle(
            "Greeting", 
            "Hello from iOS!", 
            UIAlertControllerStyleAlert
        )
        alert.addAction(UIAlertAction.actionWithTitle("OK", UIAlertActionStyleDefault, null))

        val window = UIApplication.sharedApplication.keyWindow
        window?.rootViewController?.presentViewController(alert, animated = true, completion = null)
    }
}

期待値と実装の使い分け


プラットフォームごとに異なる実装が必要な場合、expectactualキーワードを使います。

共通コード (commonMain)

expect class PlatformGreeting {
    fun greet()
}

Android固有コード (androidMain)

actual class PlatformGreeting {
    actual fun greet() {
        println("Hello from Android!")
    }
}

iOS固有コード (iosMain)

actual class PlatformGreeting {
    actual fun greet() {
        println("Hello from iOS!")
    }
}

コード呼び出し例


AndroidアプリやiOSアプリから共通コードを呼び出す方法を示します。

Androidコード例

val greeting = PlatformGreeting(context)
greeting.greet()

iOSコード例

let greeting = PlatformGreeting()
greeting.greet()

Kotlin Multiplatformを使えば、効率よく共通コードを作成しつつ、プラットフォームごとの機能も柔軟に実装できます。次は、ライブラリと依存関係の追加について解説します。

ライブラリと依存関係の追加


Kotlin Multiplatformプロジェクトでは、共通コードやプラットフォーム固有コードで利用するためにライブラリを追加できます。ここでは、ライブラリの追加方法と依存関係の設定について解説します。

Gradleでの依存関係の追加方法


Kotlin Multiplatformプロジェクトでは、build.gradle.ktsファイル内で依存関係を追加します。sourceSetsごとに必要なライブラリを指定します。

共通ライブラリの追加例
共通コードで利用するライブラリは、commonMainに追加します。

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2")
                implementation("io.ktor:ktor-client-core:2.0.0")
            }
        }
    }
}

Android固有ライブラリの追加例
Android用のライブラリは、androidMainに追加します。

val androidMain by getting {
    dependencies {
        implementation("androidx.core:core-ktx:1.9.0")
        implementation("io.ktor:ktor-client-android:2.0.0")
    }
}

iOS固有ライブラリの追加例
iOS用のライブラリは、iosMainに追加します。

val iosMain by getting {
    dependencies {
        implementation("io.ktor:ktor-client-ios:2.0.0")
    }
}

依存関係のバージョン管理


バージョンを統一するために、build.gradle.kts内でバージョン番号を変数として管理する方法があります。

val ktorVersion = "2.0.0"

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-core:$ktorVersion")
            }
        }
        val androidMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-android:$ktorVersion")
            }
        }
        val iosMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-ios:$ktorVersion")
            }
        }
    }
}

ライブラリのリポジトリ設定


依存関係をダウンロードするリポジトリは、settings.gradle.ktsまたはbuild.gradle.ktsに設定します。

repositories {
    mavenCentral()
    google()
}

サンプルプロジェクトの依存関係設定


以下は、共通コードでKtorとKotlinx Coroutinesを使用し、AndroidとiOS固有のクライアント実装を追加する例です。

kotlin {
    android()
    iosX64()
    iosArm64()

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2")
                implementation("io.ktor:ktor-client-core:2.0.0")
            }
        }
        val androidMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-android:2.0.0")
            }
        }
        val iosMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-ios:2.0.0")
            }
        }
    }
}

依存関係追加後のビルド確認


依存関係を追加したら、以下の手順でビルドが正しく行われるか確認します。

  1. Gradle Syncを実行:
    IntelliJ IDEAまたはAndroid Studioで「Sync Now」をクリック。
  2. ビルドの実行:
    ターミナルで以下のコマンドを実行。
   ./gradlew build
  1. エラー確認:
    依存関係のエラーがないかログを確認します。

これで、Kotlin Multiplatformプロジェクトへのライブラリと依存関係の追加が完了です。次は、ビルドとテストの実行方法について解説します。

ビルドとテストの実行


Kotlin Multiplatformプロジェクトを効率的に開発するには、ビルドとテストの実行方法を理解することが重要です。ここでは、ビルドプロセスとテストの基本的な手順を解説します。

ビルドの実行方法

Kotlin MultiplatformプロジェクトのビルドはGradleタスクを使用して行います。以下のコマンドを使ってビルドを実行できます。

全プラットフォーム向けにビルド

./gradlew build

Androidのみビルド

./gradlew :androidApp:assembleDebug

iOS向けビルド
iOSビルドにはXcodeのビルドツールを使用します。

./gradlew :shared:packForXcode

テストの作成と実行

Kotlin Multiplatformでは、共通コードやプラットフォーム固有コードに対してテストを書くことができます。

共通コードのテスト


共通コード用のテストはcommonTestソースセットに記述します。

ディレクトリ構成

shared/
└── src/
    ├── commonMain/
    │   └── kotlin/
    │       └── SampleClass.kt
    └── commonTest/
        └── kotlin/
            └── SampleClassTest.kt

共通テストの例

package com.example.shared

import kotlin.test.Test
import kotlin.test.assertEquals

class SampleClassTest {
    @Test
    fun testSampleFunction() {
        val result = SampleClass().sampleFunction()
        assertEquals("Hello, Kotlin Multiplatform!", result)
    }
}

Android固有コードのテスト


Android固有のテストはandroidTestソースセットに記述します。

ディレクトリ構成

shared/
└── src/
    └── androidTest/
        └── kotlin/
            └── AndroidSampleTest.kt

Androidテストの例

package com.example.shared

import org.junit.Test
import org.junit.Assert.assertTrue

class AndroidSampleTest {
    @Test
    fun testAndroidFunction() {
        assertTrue(true)
    }
}

iOS固有コードのテスト


iOSのテストはiosTestソースセットに記述します。

ディレクトリ構成

shared/
└── src/
    └── iosTest/
        └── kotlin/
            └── IOSSampleTest.kt

iOSテストの例

package com.example.shared

import kotlin.test.Test
import kotlin.test.assertTrue

class IOSSampleTest {
    @Test
    fun testIOSFunction() {
        assertTrue(true)
    }
}

テストの実行方法

すべてのテストを実行

./gradlew test

Androidテストのみ実行

./gradlew :shared:connectedAndroidTest

iOSテストの実行
Xcodeを使用してiOS向けテストを実行します。

./gradlew :shared:iosX64Test

テスト結果の確認


テスト実行後、結果は以下のディレクトリに出力されます。

  • Androidテスト結果: shared/build/reports/androidTests/connected/
  • 共通・iOSテスト結果: shared/build/reports/tests/testDebug/

これで、Kotlin Multiplatformプロジェクトのビルドとテストの基本的な実行方法を理解できました。次は、デバッグとトラブルシューティングについて解説します。

デバッグとトラブルシューティング


Kotlin Multiplatformプロジェクトを開発する際、デバッグや問題解決の方法を知っておくことが重要です。ここでは、共通コード、Android、iOS向けのデバッグ方法と、よくある問題への対処法について解説します。

共通コードのデバッグ


共通コードのデバッグは、IntelliJ IDEAやAndroid Studioのデバッガを使用します。

  1. ブレークポイントの設定:
  • 共通コードにブレークポイントを設定します。
  • 例: shared/src/commonMain/kotlin/Example.kt内の任意の行にブレークポイントを置きます。
  1. デバッグ実行:
  • AndroidまたはiOSターゲットでデバッグモードを開始します。
  • Androidの場合: Run -> Debug 'AndroidApp'
  • iOSの場合: Xcodeからデバッグ実行。
  1. 変数やステップ実行:
  • デバッガの機能を使って変数の値を確認し、ステップ実行で処理の流れを追います。

Android固有コードのデバッグ

  1. エミュレータまたは実機でデバッグ:
    Android Studioで、エミュレータや接続した実機でデバッグを実行します。
   ./gradlew :androidApp:assembleDebug
  1. Logcatを使用:
    Logcatでログを確認し、エラーや警告を調査します。
   Log.d("TAG", "Debug message")
  1. ブレークポイントの活用:
    Android固有コード内にブレークポイントを設定して、デバッグ実行します。

iOS固有コードのデバッグ

  1. Xcodeでデバッグ実行:
  • iOSアプリをXcodeで開き、シミュレータまたは実機でデバッグを開始します。
   ./gradlew :shared:packForXcode
  1. ブレークポイントの設定:
  • Xcode内でブレークポイントを設定し、コードの流れを確認します。
  1. コンソール出力:
  • Swiftコード内でデバッグ出力を利用します。
   print("Debug message")

よくある問題と解決方法

1. 依存関係の解決エラー

  • エラー内容: Could not resolve dependency...
  • 解決方法:
  1. build.gradle.ktsの依存関係が正しいか確認。
  2. Gradleのキャッシュをクリアして再ビルド。
    bash ./gradlew clean build

2. iOSビルドエラー

  • エラー内容: No such module 'shared'
  • 解決方法:
  1. Xcodeで正しいスキームを選択してビルド。
  2. GradleタスクでXcode用パッケージを再生成。
    bash ./gradlew :shared:packForXcode

3. シンボル解決エラー

  • エラー内容: Unresolved reference
  • 解決方法:
  1. ソースセットが正しく分けられているか確認。
  2. IntelliJ IDEAやAndroid StudioでInvalidate Caches / Restartを実行。

4. ネットワーク通信の問題

  • エラー内容: Network request failed
  • 解決方法:
  1. 共通コード内でネットワーク設定を確認。
  2. AndroidとiOSでネットワークパーミッションが正しく設定されているか確認。

デバッグのベストプラクティス

  1. 共通コードのロジックテスト: 共通コードはユニットテストでしっかりカバーする。
  2. プラットフォームごとの確認: 各プラットフォームでの挙動を個別にデバッグする。
  3. ログ出力の活用: 共通コードではシンプルなログ出力を活用し、プラットフォーム固有のデバッグ手法を併用する。

これで、Kotlin Multiplatformプロジェクトのデバッグとトラブルシューティング方法が理解できました。次は、実際のアプリケーション例について解説します。

実際のアプリケーション例


Kotlin Multiplatformの理解を深めるために、簡単なクロスプラットフォームアプリを作成する例を紹介します。ここでは、AndroidとiOSで動作する天気情報アプリを実装します。共通コードでビジネスロジックを作成し、AndroidとiOSそれぞれでUIを構築します。

プロジェクト構成

WeatherApp/
│-- build.gradle.kts
│-- settings.gradle.kts
│-- shared/
│   └── src/
│       ├── commonMain/
│       │   └── kotlin/
│       │       └── WeatherRepository.kt
│       ├── androidMain/
│       │   └── kotlin/
│       │       └── AndroidPlatform.kt
│       └── iosMain/
│           └── kotlin/
│               └── IOSPlatform.kt
│-- androidApp/
│   └── src/
│       └── main/
│           └── kotlin/
│               └── MainActivity.kt
└-- iosApp/
    └── iosApp/
        └── ContentView.swift

共通コードの作成


天気情報を取得するリポジトリクラスを共通コードに作成します。

shared/src/commonMain/kotlin/WeatherRepository.kt

package com.example.shared

import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.engine.cio.*

class WeatherRepository {
    private val client = HttpClient(CIO)

    suspend fun getWeather(city: String): String {
        val apiKey = "YOUR_API_KEY"
        val url = "https://api.openweathermap.org/data/2.5/weather?q=$city&appid=$apiKey"
        return client.get(url)
    }
}

Android固有コードの作成


Android用のエントリーポイントを作成し、UIを構築します。

androidApp/src/main/kotlin/MainActivity.kt

package com.example.androidApp

import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.example.shared.WeatherRepository
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {
    private val weatherRepository = WeatherRepository()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(TextView(this).apply { text = "Loading..." })

        CoroutineScope(Dispatchers.Main).launch {
            val weatherInfo = weatherRepository.getWeather("Tokyo")
            (this@MainActivity.findViewById(android.R.id.content) as TextView).text = weatherInfo
        }
    }
}

iOS固有コードの作成


SwiftUIを使ってiOSアプリのUIを構築します。

iosApp/iosApp/ContentView.swift

import SwiftUI
import shared

struct ContentView: View {
    @State private var weatherInfo = "Loading..."

    var body: some View {
        Text(weatherInfo)
            .padding()
            .onAppear {
                Task {
                    let repository = WeatherRepository()
                    weatherInfo = try await repository.getWeather(city: "Tokyo")
                }
            }
    }
}

ビルドと実行

  1. Androidアプリのビルドと実行:
   ./gradlew :androidApp:assembleDebug


Android StudioでMainActivity.ktをデバッグ実行します。

  1. iOSアプリのビルドと実行:
   ./gradlew :shared:packForXcode


XcodeでiosApp.xcodeprojを開き、シミュレータまたは実機で実行します。

実行結果


アプリを実行すると、AndroidおよびiOSの画面に指定した都市(例: 東京)の天気情報が表示されます。

アプリケーションの拡張

  1. エラーハンドリングの追加:
    ネットワークエラーやAPIエラーを適切に処理します。
  2. UIの強化:
    プラットフォームごとにリッチなUIを追加し、よりユーザーフレンドリーにします。
  3. 機能追加:
  • 複数都市の天気情報表示
  • 位置情報を使用した天気情報取得

これで、Kotlin Multiplatformを使ったシンプルな天気アプリが完成しました。次は、Kotlin Multiplatformプロジェクトの内容を総括します。

まとめ


本記事では、Kotlin Multiplatformプロジェクトのセットアップ方法から、コード共有、プラットフォーム固有コードの実装、ライブラリの追加、ビルドとテスト、デバッグ、そして実際のアプリケーション例まで解説しました。

Kotlin Multiplatformを活用することで、AndroidやiOSといった複数のプラットフォーム向けに、効率的に共通ロジックを開発・共有できます。また、必要に応じてプラットフォーム固有の機能も柔軟にサポートし、高品質なクロスプラットフォームアプリを開発可能です。

適切な依存関係の管理、Gradle設定、デバッグ技術を習得すれば、開発効率と保守性が大幅に向上します。ぜひKotlin Multiplatformを活用して、効率的なクロスプラットフォーム開発に挑戦してください!

コメント

コメントする

目次