Kotlin Multiplatformアプリを作成する
このチュートリアルではIntelliJ IDEAを使用しますが、Android Studioでも同様に実行できます。どちらのIDEもコア機能とKotlin Multiplatformのサポートは共通しています。
これは、共有ロジックとネイティブUIを持つKotlin Multiplatformアプリを作成するチュートリアルの最初のパートです。
Kotlin Multiplatformアプリを作成する
ユーザーインターフェースを更新する
依存関係を追加する
さらにロジックを共有する
プロジェクトを完了する
ここでは、IntelliJ IDEAを使用して初めてのKotlin Multiplatformアプリケーションを作成し、実行する方法を学びます。
Kotlin Multiplatformテクノロジーは、クロスプラットフォームプロジェクトの開発を簡素化します。 Kotlin Multiplatformアプリケーションは、iOS、Android、macOS、Windows、Linux、Webなど、さまざまなプラットフォームで動作します。
Kotlin Multiplatformの主要なユースケースの1つは、モバイルプラットフォーム間でコードを共有することです。 iOSアプリとAndroidアプリ間でアプリケーションロジックを共有し、ネイティブUIを実装したりプラットフォームAPIを操作したりする必要がある場合にのみ、プラットフォーム固有のコードを記述できます。
プロジェクトを作成する
クイックスタートで、Kotlin Multiplatform開発の環境をセットアップするの手順を完了します。
IntelliJ IDEAで、File | New | Project を選択します。
左側のパネルで、Kotlin Multiplatform を選択します。
New Project ウィンドウで、以下のフィールドを指定します。
- Name:
GreetingKMP
- Group:
com.jetbrains.greeting
- Artifact:
greetingkmp
- Name:
Android および iOS ターゲットを選択します。
iOSの場合、UIをネイティブに保つために、Do not share UI オプションを選択します。
すべてのフィールドとターゲットを指定したら、Create をクリックします。
IntelliJ IDEAは、プロジェクトのAndroid Gradleプラグインを最新バージョンにアップグレードすることを自動的に提案する場合があります。 Kotlin Multiplatformは最新のAGPバージョンと互換性がないため、アップグレードはお勧めしません (互換性テーブルを参照)。
プロジェクト構造を確認する
IntelliJ IDEAで、GreetingKMP
フォルダーを展開します。
このKotlin Multiplatformプロジェクトには、3つのモジュールが含まれています。
_shared_
は、AndroidおよびiOSアプリケーションの両方に共通するロジック(プラットフォーム間で共有するコード)を含むKotlinモジュールです。ビルドプロセスを自動化するために、ビルドシステムとしてGradleを使用します。_composeApp_
は、AndroidアプリケーションとしてビルドされるKotlinモジュールです。ビルドシステムとしてGradleを使用します。composeApp
モジュールは、通常のAndroidライブラリとしてshared
モジュールに依存し、それを使用します。_iosApp_
は、iOSアプリケーションとしてビルドされるXcodeプロジェクトです。これは、iOSフレームワークとしてshared
モジュールに依存し、それを使用します。shared
モジュールは、通常のフレームワークとして、またはCocoaPodsの依存関係として使用できます。デフォルトでは、IntelliJ IDEAで作成されたKotlin Multiplatformプロジェクトは、通常のフレームワーク依存関係を使用します。
shared
モジュールは、androidMain
、commonMain
、iosMain
の3つのソースセットで構成されています。ソースセット とは、Gradleの概念で、論理的にグループ化された複数のファイル群であり、各グループが独自の依存関係を持ちます。 Kotlin Multiplatformでは、shared
モジュール内の異なるソースセットが異なるプラットフォームをターゲットにすることができます。
共通ソースセットには共有Kotlinコードが含まれ、プラットフォームソースセットは各ターゲット固有のKotlinコードを使用します。 androidMain
にはKotlin/JVMが使用され、iosMain
にはKotlin/Nativeが使用されます。
shared
モジュールがAndroidライブラリとしてビルドされると、共通KotlinコードはKotlin/JVMとして扱われます。 iOSフレームワークとしてビルドされると、共通KotlinはKotlin/Nativeとして扱われます。
共通宣言を記述する
共通ソースセットには、複数のターゲットプラットフォームで利用できる共有コードが含まれます。 これはプラットフォームに依存しないコードを含むように設計されています。共通ソースセットでプラットフォーム固有のAPIを使用しようとすると、IDEが警告を表示します。
shared/src/commonMain/kotlin/com/jetbrains/greeting/greetingkmp/Greeting.kt
ファイルを開くと、greet()
関数を持つ自動生成されたGreeting
クラスを見つけることができます。kotlinclass Greeting { private val platform = getPlatform() fun greet(): String { return "Hello, ${platform.name}!" } }
挨拶に少しバリエーションを加えます。Kotlin標準ライブラリから
kotlin.random.Random
をインポートします。 これは、すべてのプラットフォームで動作し、依存関係として自動的に含まれるマルチプラットフォームライブラリです。テキストを反転させるために、Kotlin標準ライブラリの
reversed()
呼び出しで共有コードを更新します。kotlinimport kotlin.random.Random class Greeting { private val platform: Platform = getPlatform() fun greet(): String { val firstWord = if (Random.nextBoolean()) "Hi!" else "Hello!" return "$firstWord Guess what this is! > ${platform.name.reversed()}!" } }
コードを共通Kotlinのみで記述することには、プラットフォーム固有の機能を使用できないという明白な制限があります。 インターフェースとexpect/actualメカニズムを使用することで、これを解決します。
プラットフォーム固有の実装を確認する
共通ソースセットは expect
宣言(インターフェース、クラスなど)を定義できます。 その後、各プラットフォームソースセット(この場合は androidMain
と iosMain
)は、expect
宣言に対応する actual
プラットフォーム固有の実装を提供する必要があります。
特定のプラットフォームのコードを生成する際、Kotlinコンパイラは expect
宣言と actual
宣言をマージし、actual
実装を持つ単一の宣言を生成します。
IntelliJ IDEAでKotlin Multiplatformプロジェクトを作成すると、
commonMain
モジュールにPlatform.kt
ファイルを含むテンプレートが生成されます。kotlininterface Platform { val name: String }
これは、プラットフォームに関する情報を持つ共通の
Platform
インターフェースです。androidMain
モジュールとiosMain
モジュールを切り替えます。 AndroidおよびiOSソースセットで、同じ機能の異なる実装があることがわかります。kotlin// Platform.android.kt in the androidMain module: import android.os.Build class AndroidPlatform : Platform { override val name: String = "Android ${Build.VERSION.SDK_INT}" }
kotlin// Platform.ios.kt in the iosMain module: import platform.UIKit.UIDevice class IOSPlatform: Platform { override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion }
AndroidPlatform
のname
プロパティの実装は、Android固有のコード、具体的にはandroid.os.Build
依存関係を使用します。このコードはKotlin/JVMで記述されています。ここでjava.util.Random
のようなJVM固有のクラスにアクセスしようとすると、このコードはコンパイルされます。IOSPlatform
のname
プロパティの実装は、iOS固有のコード、具体的にはplatform.UIKit.UIDevice
依存関係を使用します。これはKotlin/Nativeで記述されており、KotlinでiOSコードを記述できることを意味します。このコードはiOSフレームワークの一部となり、後でiOSアプリケーションのSwiftから呼び出します。
異なるソースセットの
getPlatform()
関数を確認します。そのexpect
宣言には本体がなく、プラットフォームコードでactual
実装が提供されています。kotlin// Platform.kt in the commonMain source set expect fun getPlatform(): Platform
kotlin// Platform.android.kt in the androidMain source set actual fun getPlatform(): Platform = AndroidPlatform()
kotlin// Platform.ios.kt in the iosMain source set actual fun getPlatform(): Platform = IOSPlatform()
ここでは、共通ソースセットが expect
な getPlatform()
関数を定義し、プラットフォームソースセットには、Androidアプリ用の AndroidPlatform()
とiOSアプリ用の IOSPlatform()
という actual
な実装があります。
特定のプラットフォームのコードを生成する際、Kotlinコンパイラは expect
宣言と actual
宣言をマージし、actual
実装を持つ単一の getPlatform()
関数を生成します。
そのため、expect
宣言と actual
宣言は同じパッケージで定義する必要があります。これにより、結果として生成されるプラットフォームコードで1つの宣言にマージされます。生成されたプラットフォームコードで expect
な getPlatform()
関数を呼び出すと、正しい actual
な実装が呼び出されます。
これで、アプリを実行してこれらすべてを実際に確認できます。
expect/actualメカニズムを探る (オプション)
テンプレートプロジェクトでは関数にexpect/actualメカニズムを使用していますが、プロパティやクラスなど、ほとんどのKotlin宣言にも機能します。expectなプロパティを実装してみましょう。
commonMain
モジュールのPlatform.kt
を開き、ファイルの最後に以下を追加します。kotlinexpect val num: Int
Kotlinコンパイラは、このプロパティに対応するactual宣言がプラットフォームモジュールにないと警告します。
以下の方法で直ちに実装を提供してみてください。
kotlinexpect val num: Int = 42
expect宣言には本体(この場合は初期化子)があってはならないというエラーが表示されます。実装はactualプラットフォームモジュールで提供する必要があります。初期化子を削除してください。
num
プロパティにマウスオーバーし、Create missed actuals... をクリックします。androidMain
ソースセットを選択します。その後、androidMain/Platform.android.kt
で実装を完了できます。kotlinactual val num: Int = 1
次に、
iosMain
モジュールの実装を提供します。iosMain/Platform.ios.kt
に以下を追加します。kotlinactual val num: Int = 2
commonMain/Greeting.kt
ファイルで、num
プロパティをgreet()
関数に追加して違いを確認します。kotlinfun greet(): String { val firstWord = if (Random.nextBoolean()) "Hi!" else "Hello!" return "$firstWord [$num] Guess what this is! > ${platform.name.reversed()}!" }
アプリケーションを実行する
IntelliJ IDEAから、AndroidとiOSの両方でマルチプラットフォームアプリケーションを実行できます。
以前にexpect/actualメカニズムを試したことがある場合、Androidの挨拶には「[1]」が、iOSの挨拶には「[2]」が追加されていることがわかります。
Androidでアプリケーションを実行する
実行構成のリストで、composeApp を選択します。
構成リストの横にあるAndroid仮想デバイスを選択し、Run をクリックします。
リストにデバイスがない場合は、新しいAndroid仮想デバイスを作成してください。
別のAndroidシミュレートデバイスで実行する
Androidエミュレーターを構成し、別のシミュレートデバイスでアプリケーションを実行する方法を学びます。
実機Androidデバイスで実行する
ハードウェアデバイスを構成して接続し、その上でアプリケーションを実行する方法を学びます。
iOSでアプリケーションを実行する
初期設定の一部としてXcodeを起動していない場合は、iOSアプリを実行する前に起動してください。
IntelliJ IDEAで、実行構成のリストから iosApp を選択し、実行構成の横にあるシミュレートデバイスを選択して、Run をクリックします。
リストに利用可能なiOS構成がない場合は、新しい実行構成を追加してください。
新しいiOSシミュレートデバイスで実行する
シミュレートデバイスでアプリケーションを実行したい場合は、新しい実行構成を追加できます。
実行構成のリストで、Edit Configurations をクリックします。
構成リストの上にある + ボタンをクリックし、Xcode Application を選択します。
構成に名前を付けます。
Working directory を選択します。そのためには、例えば KotlinMultiplatformSandbox のようなプロジェクトの
iosApp
フォルダーに移動します。Run をクリックして、新しいシミュレートデバイスでアプリケーションを実行します。
実機iOSデバイスで実行する
実機のiOSデバイスでマルチプラットフォームアプリケーションを実行できます。開始する前に、Apple IDに関連付けられたチームIDを設定する必要があります。
チームIDを設定する
プロジェクトでチームIDを設定するには、IntelliJ IDEAのKDoctorツールを使用するか、Xcodeでチームを選択できます。
KDoctorの場合:
IntelliJ IDEAで、ターミナルで以下のコマンドを実行します。
nonekdoctor --team-ids
KDoctorは、現在システムに構成されているすべてのチームIDをリスト表示します。例えば:
text3ABC246XYZ (Max Sample) ZABCW6SXYZ (SampleTech Inc.)
IntelliJ IDEAで
iosApp/Configuration/Config.xcconfig
を開き、チームIDを指定します。
別の方法として、Xcodeでチームを選択します。
Xcodeに移動し、Open a project or file を選択します。
プロジェクトの
iosApp/iosApp.xcworkspace
ファイルに移動します。左側のメニューで
iosApp
を選択します。Signing & Capabilities に移動します。
Team リストでチームを選択します。
まだチームを設定していない場合は、Team リストの Add an Account オプションを使用し、Xcodeの指示に従ってください。
バンドル識別子が一意であり、署名証明書が正常に割り当てられていることを確認してください。
アプリを実行する
iPhoneをケーブルで接続します。すでにデバイスがXcodeに登録されている場合、IntelliJ IDEAは実行構成のリストにそれを表示するはずです。対応する iosApp
構成を実行します。
まだiPhoneをXcodeに登録していない場合は、Appleの推奨事項に従ってください。 要するに、次のことを行う必要があります。
- iPhoneをケーブルで接続します。
- iPhoneで、設定 | プライバシーとセキュリティ で開発者モードを有効にします。
- Xcodeで、上部メニューに移動し、Window | Devices and Simulators を選択します。
- プラス記号をクリックします。接続されているiPhoneを選択し、Add をクリックします。
- Apple IDでサインインして、デバイスでの開発機能を有効にします。
- 画面の指示に従ってペアリングプロセスを完了します。
XcodeでiPhoneを登録したら、IntelliJ IDEAで新しい実行構成を作成し、Execution target リストでデバイスを選択します。対応する iosApp
構成を実行します。
次のステップ
チュートリアルの次のパートでは、プラットフォーム固有のライブラリを使用してUI要素を更新する方法を学びます。
関連項目
- コードが正しく動作することを確認するために、マルチプラットフォームテストを作成して実行する方法を参照してください。
- プロジェクト構造について詳しく学びます。
- 既存のAndroidプロジェクトをクロスプラットフォームアプリに変換したい場合は、このチュートリアルを完了してAndroidアプリをクロスプラットフォーム化してください。
ヘルプ
- Kotlin Slack。招待状を取得し、#multiplatformチャンネルに参加してください。
- Kotlin課題トラッカー。新しい課題を報告する。