mcpField
K
kmp-boundaries

kmp-boundaries

github.com/rcosteira79開発165140 回インストール6 週間前に更新
リポジトリ

kmp-boundaries について

Kotlin Multiplatformで共有コードとプラットフォーム実装の境界を設計するスキルです。機能別インターフェース、Activityが所有するAndroid UIバインディング、AGP 9のKMPライブラリ制約を扱います。

主な機能

  1. 01意味を表すcommonMainインターフェース
  2. 02機能別のプラットフォーム境界
  3. 03ActivityスコープのAndroid UIバインディング
  4. 04AGP 9 KMPライブラリの制約
  5. 05iOS–Swift相互運用のリファレンス

活用シーン

  1. 01プラットフォーム機能の共有API設計
  2. 02AndroidバインディングのActivityライフサイクル漏れ防止
  3. 03AndroidアプリのAGP 9 KMPライブラリへの移行
  4. 04Swift呼び出し向けKotlin APIの準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rcosteira79/android-skills --skill kmp-boundaries

インストール後、Claude Code で/kmp-boundariesを入力して読み込まれたか確認します。

同梱ファイルreferences/ios-interop.md

詳細

Kotlin Multiplatform の境界設計

KMP の境界に関する基本ルール:

  • commonMain はセマンティックに保つ — Android/iOS の仕組みではなく、プロダクトが必要とする 内容 を表します。currentRegion() とし、currentRegionFromAndroidLocale(context) とはしません。
  • 機能ごとに分割する — 1 つの巨大な Platform オブジェクトではなく、Clipboard、ShareSheet、Haptics、Biometrics を個別のインターフェースにします。
  • actual は薄く保つ — actual の役割は変換であり、判断ではありません。actual 内にビジネスロジックの if/when がある場合は、それを common に置き、フェイクでテストします。
  • フェイク/DI/ライフサイクル/実行時の選択が必要な場合は、expect class よりも common の interface とプラットフォームごとのバインディングを優先します。
  • 中間ソースセット(skikoMain、appleMain)を導入するのは、2 つのプラットフォームで実際の実装を本当に共有する場合に限ります。

以下では、特に詳しく扱う境界を 2 つ紹介します。Activity が所有するプラットフォーム UI 境界と、AGP 9 の KMP ライブラリに関する制約です。

関連項目: android-skills:kmp-ktor(ネットワーク境界)、compose/references/multiplatform.md(Compose-MP の仕組み)、android-skills:kotlin-coroutines(スコープの所有権)。iOS↔Swift ブリッジ(Kotlin→Swift の命名、型幅(Int は 32 ビット)、SKIE による suspend→async/Flow→AsyncSequence、sealed クラスの網羅性、SwiftUI への埋め込み)については、iOS 側の actual を作成する際に references/ios-interop.md を読み込んでください。

プラットフォーム UI バインディングは Context ではなく Activity が所有する

Android の境界における最もよくある間違いは、実際には Activity が必要なバインディングに applicationContext/LocalContext.current を渡し、その後 Intent.FLAG_ACTIVITY_NEW_TASK でライフサイクル上の不足を取り繕うことです。このフラグは要注意です。フォアグラウンド UI の操作であることを隠してしまいます。代わりに Activity を保持してください。

// commonMain — semantic interface; DOCUMENT what `suspend` means
interface ShareSheet {
    /** Launches the system share sheet. Returns when the sheet is PRESENTED — not when the user
     *  completes or cancels. (Otherwise callers write incorrect retry/confirmation logic.) */
    suspend fun shareText(text: String)
}

// androidMain — thin: build the intent and launch it. Activity-owned.
class AndroidShareSheet(private val activity: Activity) : ShareSheet {
    override suspend fun shareText(text: String) {
        activity.startActivity(Intent.createChooser(
            Intent(Intent.ACTION_SEND).setType("text/plain").putExtra(Intent.EXTRA_TEXT, text), null,
        ))
    }
}

Activity をアプリ全体に注入することはしません(Activity はフレームワークが作成し、ライフサイクルに紐づいているためです)。Android アプリモジュールの アクティビティスコープ でバインディングを構築します(Hilt の場合は @InstallIn(ActivityComponent::class)。Activity はデフォルトのバインディングです。Koin の場合は scoped)。commonMain から見えるのはインターフェースだけであり、Activity がアプリモジュールの外に出ることはありません。より長いライフサイクル(アプリスコープ)を持つオブジェクトが Activity を必要とする場合は、ライフサイクルを認識するプロバイダーの背後に保持してください(onResume で設定し、onPause でクリアします)。これにより、破棄された Activity のリークを防げます。

AGP-9 KMP ライブラリの制約(構造上の制約 — 共有コードに含められるものを左右します)

AGP 9 では、KMP モジュールの Android 側で com.android.library が com.android.kotlin.multiplatform.library に置き換わり、com.android.application と kotlin.multiplatform の併用は明確に拒否されます。新しいプラグインでは、単一バリアントのアーキテクチャが強制されます。

  • BuildConfig は使用できません — コンパイル時定数には、BuildKonfig または注入された AppConfiguration インターフェースを使用します。BuildConfig.X が存在することを前提とした commonMain API は設計しないでください。
  • ビルドバリアントはありません — バリアント固有の依存関係、リソース、署名設定はアプリモジュールに置きます。デバッグ版かリリース版かの判断は、KMP モジュール内でビルドバリアントを分けるのではなく、共有コードに注入する実行時設定値として渡します。
  • NDK / JNI は使用できません — ネイティブコード(C/C++)は別の com.android.library モジュールに切り出し、KMP モジュールが利用する共通インターフェースの背後にラップします。
  • Compose-MP リソースは明示的に有効化する必要があります — kotlin { android { … } } 内に androidResources { enable = true } を追加してください。追加しないと、Android で実行時に Res.string.* / Res.drawable.* がクラッシュします(ビルド自体は成功するため、見落としやすい点です)。
  • コンシューマー向け ProGuard ルールの移行が必要です — 古い android {} ブロックの consumerProguardFiles("rules.pro") は通知なしに無視されます。新しい DSL では consumerProguardFiles.add(file("rules.pro")) を使用してください。
  • KMP モジュールを com.android.application として使うことはできません — Android のエントリーポイント(MainActivity、Application クラス、ランチャーマニフェスト、applicationId / targetSdk / versionCode / versionName)は、共有ライブラリに依存する別の androidApp モジュールに移します。MainActivity、アプリレベルの Hilt 設定、ナビゲーションホストの配線はすべて、共有モジュールの androidMain から移動します。
  • kapt は AGP 9 の組み込み Kotlin と互換性がありません — アノテーションプロセッサを KSP(2.3.1 以降)に移行するか、KSP に相当するものがないプロセッサでは com.android.legacy-kapt に切り替えます。
懸念事項AGP 9 より前(モノリシック)AGP 9 の KMP ライブラリ
MainActivity、Application クラス、ランチャーマニフェスト共有モジュールの androidMain別の androidApp モジュール
applicationId、versionCode、targetSdk共有モジュールの android {}androidApp のみ
コンパイル時定数(環境、フラグ)BuildConfig フィールドcommon の BuildKonfig、または実行時 DI
NDK / JNI のネイティブコードandroidMain(任意のモジュール)共通インターフェースを介した別の com.android.library

既存のプロジェクトを移行する場合は、具体的な手順について JetBrains の kotlin-tooling-agp9-migration スキルを参照してください。

コメント