Skip to content

Instantly share code, notes, and snippets.

View senseilearning's full-sized avatar

senseilearning senseilearning

View GitHub Profile
はい、承知いたしました。FengNiaoをKMP (Kotlin Multiplatform) プロジェクトで効果的に使うための方法を、注意点を含めてステップバイステップで解説します。
はじめに:KMPプロジェクトにおける重要な注意点 ⚠️
最も重要な点は、FengNiaoはKotlinのコードを解析できないということです。
FengNiaoはSwiftやObjective-Cのコード(.swift, .m, .hファイル)とXcodeのUIファイル(.xib, .storyboard)をスキャンして、画像リソースが使われているか(UIImage(named: "...")など)を判断します。
そのため、KMPプロジェクトで画像が**commonMainやiosMainのKotlinコード内でのみ使用されている場合、FengNiaoはそれらを「未使用」と誤って検出してしまいます**。
この制限を理解した上で、以下の手順を踏むことでFengNiaoを安全かつ効果的に利用できます。
KMPプロジェクトでFengNiaoを効果的に使う手順
この手順のゴールは、「FengNiaoでiOSネイティブ側の未使用画像を検出しつつ、Kotlin側で使っている画像を誤って削除しないようにする」ことです。
ステップ1:FengNiaoのインストール
まだインストールしていない場合、Homebrewを使うのが最も簡単です。ターミナルで以下のコマンドを実行してください。
KMP (Kotlin Multiplatform) プロジェクトでiOSのビルドを高速化するには、Kotlin/Nativeのコンパイル設定とXcodeのビルド設定の両方からアプローチするのが効果的です。
特に、開発中のデバッグビルドを高速化する設定はすぐに試せるものが多いです。
🚀 すぐに試せる!効果の高い高速化設定
開発環境(ローカルマシン)での日々のビルドを高速化するための、即効性のある設定です。gradle.propertiesファイルに以下の記述を追加・変更してください。
# Kotlin/Nativeのコンパイルキャッシュを有効にする (デバッグビルド向け)
# Kotlin 1.9.20以降はデフォルトで 'static' になりましたが、明示的に設定します。
kotlin.native.cacheKind=static
# デバッグビルド時は最適化を無効にする
kotlin.native.optimization.enabled=false
KMPプロジェクトでContextを扱うには、プラットフォーム固有のContext(Android)やそれに類する機能(iOS)を、commonMainで利用可能な形に抽象化する必要があります。主な方法として、Kotlin Multiplatformの**expect/actualメカニズム**を利用する方法と、依存性注入(DI)ライブラリ(Koinなど)を活用する方法の2つがあります。
一般的に、小規模な場合はexpect/actualが手軽ですが、多くの機能でContextが必要になる場合は、コードの疎結合を促進し、テストを容易にするDIの利用が推奨されます。
expect/actual を利用する方法
この方法は、commonMainで「期待される」(expect)宣言を行い、各プラットフォームのソースセット(androidMainやiosMain)でその「実際の」(actual)実装を提供するKMPの基本的な機能です。
1. commonMainでexpectを宣言
共有コードで必要となる機能をインターフェースやクラスとしてexpect宣言します。ここでは、アプリケーションのコンテキスト情報を持つAppContextというexpectクラスを定義する例を示します。
// in commonMain/kotlin
package com.example.project
expect class AppContext
素晴らしいです!`setPlaybackState()`が呼ばれている、というご報告、ありがとうございます。
デバッグが非常に順調に進んでいますね。そこまでくれば、ゴールは本当に目の前です。
`setMetadata()`(曲情報の設定)と `setPlaybackState()`(再生状態の設定)の両方が `MediaSession` に伝わっているにもかかわらず、メディアコントロールが表示されない。
この状況で最後に残された、そして最も可能性が高い原因は、**サービスが「フォアグラウンドサービス」として実行されていない**ことです。
### なぜ「フォアグラウンドサービス」が必要なのか?
Android 8 (Oreo) 以降、OSはバッテリー消費を節約するため、バックグラウンドで動作するアプリの処理に厳しい制限を設けました。
Coil3のAsyncImageで画像が表示されない場合、いくつかの基本的な点から確認していくのがおすすめです。URLがブラウザで開けるとのことなので、URL自体は正しい可能性が高いですね。
以下の点を見直してみてください。
1. インターネット接続の権限
まず、アプリがインターネットに接続する権限を持っているか確認します。AndroidManifest.xmlファイルに以下の記述があるか確認してください。
<uses-permission android:name="android.permission.INTERNET" />
2. AsyncImageの基本的な使い方とレイアウト
AsyncImageがUI上で表示されるためのサイズを持っているか確認してください。Modifierでサイズが指定されていないと、画像の読み込みが成功しても表示されません。
import coil3.compose.AsyncImage
Ktorで HttpTimeout が not defined (未定義) というエラーでクラッシュする場合、Ktorのタイムアウトプラグインが正しく設定されていない可能性が非常に高いです。
見直すべき点は、主に次の3つです。
* Gradleの依存関係 (build.gradle.kts)
* Ktorクライアントの初期化コード
* Ktorのバージョン
## 1. Gradleの依存関係を確認する 🐘
HttpTimeout プラグインは ktor-client-core ライブラリに含まれています。まず、この依存関係が app/build.gradle.kts (または build.gradle) に正しく追加されているか確認してください。
また、HTTP/3を利用しているとのことなので、クライアントエンジン(通常は CIO)の依存関係も必要です。
app/build.gradle.kts を確認・追記してください:
dependencies {
`MyQuery` のような Apollo Kotlin が生成するクエリクラスは、通常、プロジェクトの **`build` ディレクトリ内**に出力されます。
### 基本的な出力先パス
生成されるファイルの一般的なパスのパターンは以下のようになります。
```
プロジェクトルート/モジュール名/build/generated/source/apollo/<sourceSetName>/<パッケージ名>/MyQuery.kt
import Foundation
enum FileError: Error {
case fileNotFound
case dataReadError(Error)
}
func loadMp3DataFromBundle(fileName: String, fileExtension: String = "mp3") -> Result<Data, FileError> {
// 1. バンドルからファイルのURLを取得
guard let fileURL = Bundle.main.url(forResource: fileName, withExtension: fileExtension) else {
もちろん、以下が **Kotlin Multiplatform (KMP) プロジェクトで `git submodule` を使って別の KMP プロジェクトを参照する方法** の Markdown 形式のまとめです。
---
# Kotlin Multiplatform プロジェクトで git submodule を使って他の KMP プロジェクトを参照する方法
## 前提
- **メインプロジェクト**: `MainKMPProject`
- **サブプロジェクト(参照元)**: `SubKMPProject`(Git リポジトリ管理されている)
GitHub Packages に Kotlin Multiplatform ライブラリを組織内限定で公開する方法(ステップバイステップ)
1. GitHub リポジトリを用意
- Organization 内にリポジトリを作成
- リポジトリは「Private」に設定(パッケージも限定公開になる)
2. build.gradle.kts に以下を追加
publishing {