Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】The Swift Android Setup I Always Wanted

2025年09月12日に「Dev.to」が公開したITニュース「The Swift Android Setup I Always Wanted」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

Swift 6とJNIKitの登場で、SwiftによるAndroidネイティブコード開発が容易になった。VSCode拡張とDockerでプロジェクトを構築し、KotlinとSwift間でデータ送受信や非同期処理の方法を具体例で解説。Swift開発者がAndroidのネイティブ機能を効率的に実装できる。

出典: The Swift Android Setup I Always Wanted | Dev.to公開日:

ITニュース解説

「The Swift Android Setup I Always Wanted」という記事は、Swift 6のAndroid NDK(Native Development Kit)サポートの進化を背景に、SwiftでAndroidネイティブライブラリを開発する具体的な手法を紹介している。Swift開発者にとって、Androidプラットフォームでネイティブコードを実行できるようになったことは画期的な進歩である。この開発を可能にする主要なツールがJNIKitであり、Swift Stream IDEというVisual Studio Code(VSCode)の拡張機能を通じて、開発プロセスが大幅に簡素化された。

この開発環境を構築するには、まずDockerとVSCodeが必要である。VSCodeには、Dev Containers拡張機能とSwift Stream IDE拡張機能のインストールが求められる。これらのツールは、オペレーティングシステムに依存せず、DockerとVSCodeが動作すればどのような環境でも利用できる点が利点である。必要に応じて、後でライブラリをテストするためにAndroid Studioをインストールすることも推奨される。

新しいプロジェクトを作成する手順は、Swift Stream IDE拡張機能によってガイドされる。VSCodeのサイドバーにあるSwift Streamアイコンをクリックし、「Start New Project」を選択する。プロジェクト名、プロジェクトタイプとして「Android -> Library」、そしてJavaの名前空間(例: com.example.mylib)を入力する。続けて、Androidの最小SDKバージョンとコンパイルSDKバージョンを選択し、プロジェクト作成を開始する。このプロセスでは、VSCodeがプロジェクトファイルを生成し、Dockerイメージのダウンロードを開始する。このイメージには、すぐに使えるAndroid開発環境が含まれており、Swiftツールチェーン、Swift for Android SDK、Gradle、Android NDK、Android SDKといった必要なツールがコンテナ内で自動的にダウンロード・設定される。初回の設定には時間がかかる場合があるが、これらのツールはDockerボリュームにキャッシュされるため、二回目以降のプロジェクト作成やビルドは非常に高速になる。

SwiftでAndroidネイティブコードを記述する上で中心的な役割を果たすのが、Java Native Interface(JNI)である。JNIは、Java仮想マシン(JVM)とC++やSwiftのようなネイティブコードとの間で通信を行うための橋渡しとなる仕組みである。JavaコードはAndroid SDKを使用するが、ネイティブ言語はAndroid NDKを介してJNIを利用し、Javaと連携する。JNIの直接的な使用は低レベルで複雑になりがちだが、JNIKitはこの低レベルなJNI呼び出しをSwiftらしい、より扱いやすい形にラップすることで、開発者の生産性を高める。

Swift Streamで作成されるプロジェクトは、基本的に純粋なSwift Package Managerプロジェクトである。Swiftコードは通常、Sources/<ターゲット名>/Library.swiftに記述され、JNIKitやAndroidLoggingといったライブラリに依存する。AndroidライブラリはLibraryフォルダにGradleプロジェクトとして自動生成されるか、Swift Streamサイドバーから手動で作成できる。

Swiftコード側では、initializeメソッドがエントリポイントとなる。このメソッドはJava/Kotlin側から呼び出される必要があり、他のネイティブメソッドが呼び出される前に一度だけ実行される。@_cdecl属性を使用し、JNIの特定の命名規則(Java_<パッケージ>_<クラス>_<メソッド>)に従うことで、Java/Kotlinからアクセス可能な関数として公開する。このメソッドの引数には、JNI環境へのポインタであるenvPointerと、クラスまたはインスタンスへのポインタであるclazzRefまたはthizRefが必須で含まれる。initializeメソッドの内部では、Androidロガーをブートストラップし、JVMとの接続をJNIKitを通じて初期化する。

JNI利用時の重要な注意点として、デフォルトのシステムクラスローダーでは、アプリケーション固有のクラスやGradle依存関係のクラスを認識できないという問題がある。この問題を解決するため、アプリケーションのクラスローダーを一度取得し、JNIKitのキャッシュに保存して、常にそのクラスローダーを使用する方法が推奨される。これにより、アプリのライフサイクル全体で動的にロードされたクラスへのアクセスが可能となる。また、JNI環境(JNIEnv)はスレッドに紐づくため、Swiftの非同期処理などでスレッドを切り替える際には、JEnv.current()を使用して新しいスレッドにJNI環境をアタッチする必要がある。

Java/Kotlin側では、Swiftで公開されたネイティブメソッドに対応するexternal修飾子をつけたメソッドを定義する。例えば、Kotlinではexternal fun initialize(caller: Any)のように記述する。このKotlinコードはSwift Streamによって自動生成される。また、アプリケーションの起動時にSystem.loadLibrary("MyFirstAndroidProject")を呼び出し、Swiftでコンパイルされたネイティブライブラリをロードする必要がある。

Swiftプロジェクトのビルドは、Swift Streamタブの「Project -> Build」から実行する。デバッグまたはリリーススキームを選択すると、ビルドプロセスが開始される。初回ビルドではGradle wrapperのセットアップなどに時間がかかることがあるが、キャッシュ機能により二回目以降は短時間で完了する。このビルドプロセスにより、JavaライブラリのGradleプロジェクトが自動的に生成される。

生成されたAndroidライブラリプロジェクトには、SwiftInterface.ktのようなボイラープレートコードが含まれる。Swift Stream IDEは、Gradleプロジェクトの管理も行い、settings.gradle.ktsbuild.gradle.ktsファイルを自動的に同期する。Swiftのランタイムライブラリは、デフォルトでSwifDroidランタイムライブラリのJitPackリポジトリから自動的に取得されるため、.soファイルの手動コピーは不要である。.vscode/android-stream.jsonという設定ファイルを通じて、パッケージ名、SDKバージョン、Javaバージョン、Swiftコンパイラ引数などのプロジェクト設定を詳細に制御できる。最終的に、配布可能なAndroidライブラリファイル(.aar)を生成するには、Swift Streamサイドバーの「Java Library Project -> Assemble」コマンドを実行する。

この生成された.aarファイルを既存のAndroidプロジェクトに組み込むには、まずAndroid Studioでプロジェクトを開き、settings.gradle.ktsファイルにJitPackリポジトリを追加する。次に、アプリモジュールのbuild.gradle.kts.aarファイルと必要なランタイムライブラリを依存関係として追加する。.aarファイルは、Swift StreamプロジェクトのLibrary/myfirstandroidproject/build/outputs/aar/パスからAndroid Studioプロジェクトのapp/libsフォルダに手動でコピーする必要がある。これらの設定が完了したら、AndroidアプリのApplicationクラスかメインアクティビティのonCreateメソッドでSwiftInterface.initialize(this)を呼び出し、Swiftコードを初期化する。これにより、LogCatでSwiftからのログメッセージを確認できるようになり、SwiftコードがAndroid上で正常に動作していることを確認できる。

Swiftコードに変更を加えた際の開発ループは、Swift Streamで「Project -> Build」、続けて「Java Library Project -> Assemble」を実行し、新しい.aarファイルをAndroidプロジェクトのapp/libsフォルダにコピーして置き換える、という手順で繰り返される。その後、Androidアプリをリビルドして実行する。

SwiftとKotlinの間で様々なデータ型をやり取りするJNI連携の具体的な例も示されている。KotlinからInt、IntArray、String、DateオブジェクトをSwiftに送る方法や、SwiftからStringをKotlinに返す方法などが紹介されている。特にIntArrayやString、Dateオブジェクトを扱う際には、JNIの低レベルな参照を適切に管理し、Swiftの型に変換するためのJNIKitの機能が活用される。Swiftの非同期/awaitコードをKotlinから実行する例では、@_cdecl属性が非同期オペレータに対応しないため、DispatchSemaphoreを用いて非同期タスクの完了を待機する方法が示されている。ただし、この方法はUIスレッドでの使用はデッドロックを引き起こす可能性があるため、バックグラウンド処理に限るべきである。

さらに、Javaの既存クラスをSwiftでより「Swiftらしい」方法で扱うためのラッパーを作成する概念も重要である。java.util.Dateクラスを例にとり、JDateというSwiftラッパーを作成する方法が解説されている。JDateJObjectableプロトコルに準拠し、JClass.loadでJavaクラスをロードし、newObjectでインスタンスを生成する。callIntMethodcallBoolMethodなどのメソッドを使って、JavaオブジェクトのメソッドをSwiftから呼び出すことができる。これにより、JavaとSwiftの間でよりシームレスな連携が可能となり、既存のJavaライブラリ資産をSwiftコードから活用できる。

これらの手法を理解し実践することで、システムエンジニアの初心者はSwiftでAndroidネイティブアプリケーションの一部を開発し、既存のAndroidプロジェクトに統合する方法を学ぶことができる。JNIKitとSwift Stream IDEは、この複雑なクロスプラットフォーム開発を大幅に簡素化する強力なツールである。今後の記事では、JitPackを通じたライブラリ配布や、UI連携など、さらに高度なJNI活用法が紹介される予定である。

関連コンテンツ

関連IT用語