Skip to content

クロスプラットフォームモバイルアプリケーションの作成

Ktor HTTPクライアントはマルチプラットフォームプロジェクトで使用できます。このチュートリアルでは、リクエストを送信し、レスポンスボディをプレーンなHTMLテキストとして受け取るシンプルなKotlin Multiplatform Mobileアプリケーションを作成します。

最初のKotlin Multiplatform Mobileアプリケーションの作成方法については、最初のクロスプラットフォームモバイルアプリを作成するを参照してください。

前提条件

まず、適切なオペレーティングシステムに必要なツールをインストールして、クロスプラットフォームモバイル開発のための環境をセットアップする必要があります。これを行う方法については、環境をセットアップするセクションを参照してください。

このチュートリアルの一部の手順(iOS固有のコード記述やiOSアプリケーションの実行など)を完了するには、macOSを搭載したMacが必要です。

新しいプロジェクトを作成する

新しいKotlin Multiplatformプロジェクトを開始するには、2つのアプローチがあります。

  • Android Studio内でテンプレートからプロジェクトを作成できます。
  • あるいは、Kotlin Multiplatform Wizardを使用して新しいプロジェクトを生成できます。このウィザードでは、プロジェクトのセットアップをカスタマイズするオプションが提供されており、例えばAndroidサポートを除外したり、Ktorサーバーを含めたりすることができます。

このチュートリアルでは、テンプレートからプロジェクトを作成するプロセスを説明します。

  1. Android Studioで、File | New | New Projectを選択します。
  2. プロジェクトテンプレートのリストからKotlin Multiplatform Appを選択し、Nextをクリックします。
  3. アプリケーションの名前を指定し、Nextをクリックします。このチュートリアルでは、アプリケーション名はKmmKtorです。
  4. 次のページで、デフォルト設定のままFinishをクリックして新しいプロジェクトを作成します。 これで、プロジェクトがセットアップされるのを待ちます。初回は、必要なコンポーネルのダウンロードとセットアップに時間がかかる場合があります。

    生成されたマルチプラットフォームプロジェクトの完全な構造を表示するには、プロジェクトビューAndroidからProjectに切り替えます。

ビルドスクリプトを構成する

Kotlin Gradleプラグインを更新する

gradle/libs.versions.tomlファイルを開き、Kotlinのバージョンを最新に更新します。

kotlin
kotlin = "2.1.20"

undefined

Ktorの依存関係を追加する

プロジェクトでKtor HTTPクライアントを使用するには、少なくとも2つの依存関係、つまりクライアント依存関係とエンジン依存関係を追加する必要があります。

gradle/libs.versions.tomlファイルにKtorのバージョンを追加します。

kotlin
[versions]
ktor = "3.2.3"

KtorのEAPバージョンを使用するには、Spaceリポジトリを追加する必要があります。

次に、Ktorクライアントとエンジンライブラリを定義します。

kotlin
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }

依存関係を追加するには、shared/build.gradle.ktsファイルを開き、以下の手順に従います。

  1. 共通コードでKtorクライアントを使用するには、commonMainソースセットにktor-client-coreの依存関係を追加します。

    kotlin
    sourceSets {
        commonMain.dependencies {
            implementation(libs.ktor.client.core)
        }
    }
  2. 必要な各プラットフォームのエンジン依存関係を対応するソースセットに追加します。

    • Androidの場合、androidMainソースセットにktor-client-okhttpの依存関係を追加します。

      kotlin
      androidMain.dependencies {
          implementation(libs.ktor.client.okhttp)
      }

      Androidでは、他のエンジンタイプも使用できます。

    • iOSの場合、iosMainktor-client-darwinの依存関係を追加します。

      kotlin
      iosMain.dependencies {
          implementation(libs.ktor.client.darwin)
      }

コルーチンを追加する

Androidコードでコルーチンを使用するには、kotlinx.coroutinesをプロジェクトに追加する必要があります。

  1. gradle/libs.versions.tomlファイルを開き、コルーチンのバージョンとライブラリを指定します。

    kotlin
    [versions]
    coroutines = "1.9.0"
    [libraries]
    kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
    kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
  2. build.gradle.ktsファイルを開き、kotlinx-coroutines-coreの依存関係をcommonMainソースセットに追加します。

    kotlin
    sourceSets {
        commonMain.dependencies {
            implementation(libs.ktor.client.core)
            implementation(libs.kotlinx.coroutines.core)
        }
    }
  3. 次に、androidApp/build.gradle.ktsを開き、kotlinx-coroutines-androidの依存関係を追加します。

kotlin
    implementation(libs.compose.ui)
}

gradle.propertiesファイルの右上隅にあるSync Nowをクリックして、追加した依存関係をインストールします。

アプリケーションを更新する

共有コード

AndroidとiOSで共有されるコードを更新するには、shared/src/commonMain/kotlin/com/example/kmmktor/Greeting.ktファイルを開き、Greetingクラスに以下のコードを追加します。

kotlin
package com.example.kmmktor

import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*

class Greeting {
    private val client = HttpClient()

    suspend fun greeting(): String {
        val response = client.get("https://ktor.io/docs/")
        return response.bodyAsText()
    }
}
  • HTTPクライアントを作成するために、HttpClientコンストラクタが呼び出されます。
  • サスペンド関数greetingは、リクエストを行い、レスポンスのボディを文字列値として受け取るために使用されます。

Androidコード

Androidコードからサスペンド関数greetingを呼び出すには、rememberCoroutineScopeを使用します。

androidApp/src/main/java/com/example/kmmktor/android/MainActivity.ktファイルを開き、MainActivityのコードを次のように更新します。

kotlin
package com.example.kmmktor.android

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.kmmktor.Greeting
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApplicationTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    val scope = rememberCoroutineScope()
                    var text by remember { mutableStateOf("Loading") }
                    LaunchedEffect(true) {
                        scope.launch {
                            text = try {
                                Greeting().greeting()
                            } catch (e: Exception) {
                                e.localizedMessage ?: "error"
                            }
                        }
                    }
                    GreetingView(text)
                }
            }
        }
    }
}

@Composable
fun GreetingView(text: String) {
    Text(text = text)
}

@Preview
@Composable
fun DefaultPreview() {
    MyApplicationTheme {
        GreetingView("Hello, Android!")
    }
}

作成されたスコープ内で、共有のgreeting関数を呼び出し、発生しうる例外を処理できます。

iOSコード

  1. iosApp/iosApp/iOSApp.swiftファイルを開き、アプリケーションのエントリポイントを更新します。

    Swift
    import SwiftUI
    
    @main
    struct iOSApp: App {
    	var body: some Scene {
    		WindowGroup {
    			ContentView(viewModel: ContentView.ViewModel())
    		}
    	}
    }
  2. iosApp/iosApp/ContentView.swiftファイルを開き、ContentViewのコードを次のように更新します。

    Swift
    import SwiftUI
    import shared
    
    struct ContentView: View {
        @ObservedObject private(set) var viewModel: ViewModel
    
        var body: some View {
            Text(viewModel.text)
        }
    }
    
    extension ContentView {
        class ViewModel: ObservableObject {
            @Published var text = "Loading..."
            init() {
                Greeting().greeting { greeting, error in
                    DispatchQueue.main.async {
                        if let greeting = greeting {
                            self.text = greeting
                        } else {
                            self.text = error?.localizedDescription ?? "error"
                        }
                    }
                }
            }
        }
    }

    iOSでは、サスペンド関数greetingはコールバックを持つ関数として利用できます。

Androidでインターネットアクセスを有効にする

最後に行う必要があるのは、Androidアプリケーションのインターネットアクセスを有効にすることです。 androidApp/src/main/AndroidManifest.xmlファイルを開き、uses-permission要素を使用して必要なパーミッションを有効にします。

xml
<manifest>
    <uses-permission android:name="android.permission.INTERNET" />
    <application>
        ...
    </application>
</manifest>

アプリケーションを実行する

作成したマルチプラットフォームアプリケーションをAndroidまたはiOSシミュレーターで実行するには、androidAppまたはiosAppを選択し、Runをクリックします。 シミュレーターには、受信したHTMLドキュメントがプレーンテキストで表示されるはずです。

Androidシミュレーター

iOSシミュレーター