Skip to content

Most visited

Recently visited

navigation

コンセプト

前提知識

このガイドは、ネイティブ プログラミングと Android 開発に固有の概念に精通していることを前提としています。

はじめに

このセクションでは NDK の仕組みの概要を説明します。Android NDK は C または C++(ネイティブ コード)による Android アプリ開発を可能にするツールです。 特に以下のようなケースでは、ネイティブ コードを Android アプリに使用できると非常に便利です。

  • プラットフォーム間でアプリを移植する。
  • 既存のライブラリを再利用、または独自のライブラリを再利用のために提供する。
  • ゲームなど、特に演算負荷の高い処理のパフォーマンスを高める。

仕組み

このセクションでは、最初に Android 向けネイティブ アプリのビルドで使用する主要コンポーネントについて説明し、次にビルドとパッケージ化のプロセスについて説明します。

主要コンポーネント

アプリをビルドするにあたり、次のコンポーネントについて理解しておく必要があります。

  • ndk-build:ndk-build スクリプトは NDK の中核となるビルド スクリプトを開始します。このスクリプトによって次の処理が行われます。
    • 開発システムとアプリ プロジェクト ファイルを自動的に調べ、ビルド対象を決定します。
    • バイナリを生成します。
    • バイナリをアプリのプロジェクト パスにコピーします。

    詳細については ndk-build をご覧ください。

  • Java:Android の Java ソースをビルドすると .dex(Dalvik 実行形式)ファイルが生成されます。このファイルは Android OS が Dalvik 仮想マシン(「DVM」)で実行するものです。 アプリに Java ソースコードがまったく含まれていなくても、ビルドプロセスによって、ネイティブ コンポーネントを実行するための .dex 実行ファイルは生成されます。

    Java コンポーネントを開発するときは、native キーワードを使用して、メソッドがネイティブ コードとして実装されていることを示します。 たとえば、次の関数宣言では、ネイティブ ライブラリを使用して実装していることをコンパイラーに伝えています。

    public native int add(int  x, int  y);
    
  • ネイティブ共有ライブラリ:NDK はこれらのライブラリ(.so ファイル)をネイティブ ソースコードからビルドします。

    : 2 つのライブラリで同じ署名を持つ別のメソッドを実装すると、リンクエラーが発生します。 C では「シグネチャ」はメソッド名のみを意味します。一方 C++では「シグネチャ」はメソッド名や引数の名前、型も意味します。

  • ネイティブ静的ライブラリ:NDK は静的ライブラリ(.a ファイル)もビルドできます。このライブラリは他のライブラリにリンクすることができます。
  • Java Native Interface(JNI):JNI は Java コンポーネントと C++ コンポーネントの連携を可能にするインターフェースです。 このガイドは、JNI の知識があることを前提にしています。詳細については、Java Native Interface の仕様をご覧ください。
  • アプリケーション バイナリ インターフェース(ABI):ABI はアプリのマシンコードが実行時にどのようにシステムと連携するかを正確に定義したものです。 NDK はこれらの定義に対して .so ファイルをビルドします。 ABI ごとに対応するアーキテクチャは異なります。NDK には ARMEABI(既定)、MIPS、x86 に対する ABI サポートが含まれています。 詳細については、ABI 管理をご覧ください。

次の 2 つの項目は、ndk-build スクリプトを使用してビルドする、または ndk-gdb スクリプトを使用してデバッグをする場合のみ必要です。

  • Android.mk: Android.mk 設定ファイルを jni フォルダ内に作成する必要があります。 このファイルにはモジュール、モジュールの名前、コンパイル対象のソースファイル、ビルドフラグ、リンクするライブラリが定義されており、これを ndk-build スクリプトが参照します。
  • Application.mk:このファイルには、アプリに必要なモジュールのリストとモジュールの説明が含まれています。 たとえば次のような情報があります。
    • 特定のプラットフォームのコンパイルに使用する ABI。
    • ツールチェーン。
    • 組み込む標準ライブラリ(静的 STLport および動的 STLport、または既定のシステム)。

フロー

Android 向けのネイティブ アプリ開発の一般的なフローは次のとおりです。

  1. Java で実装する部分と、ネイティブ コードとして実装する部分を決定してアプリを設計します。

    : Java を完全に排除するという選択肢もありますが、Android Java フレームワークを利用した方が表示や UI の制御などの処理がしやすくなります。

  2. 他の Android プロジェクトと同様に Android アプリ プロジェクトを作成します。
  3. ネイティブ コードのみでアプリを作成している場合は、AndroidManifest.xmlNativeActivity クラスを宣言してください。 詳細については、ネイティブ アクティビティとアプリケーションをご覧ください。
  4. 「JNI」ディレクトリに Android.mk ファイルを作成し、ネイティブ ライブラリ(名前、フラグ、リンク先ライブラリを含む)とコンパイル対象のソースファイルを記載します。
  5. 任意でターゲット ABI、ツールチェーン、リリース / デバッグモード、STL を設定する Application.mk ファイルを作成することもできます。 どの値も指定しない場合、それぞれ次の既定値が使用されます。
    • ABI: armeabi
    • ツールチェーン:GCC 4.8
    • モード:リリース
    • STL: system
  6. ネイティブ ソースをプロジェクトの jni ディレクトリの下に配置します。
  7. ndk-build を使用してネイティブ(.so.a)ライブラリをコンパイルします。
  8. Java コンポーネントをビルドして、実行可能な .dex ファイルを生成します。
  9. アプリの実行に必要な .so.dex、その他のファイルなどを、すべて APK ファイルにパッケージ化します。

ネイティブ アクティビティとアプリ

Android SDK は、完全なネイティブ アクティビティを記述できるヘルパークラス NativeActivity を提供します。NativeActivity で Android フレームワークとネイティブ コード間のやり取りを処理するため、サブクラス化やメソッドの呼び出しは不要です。 AndroidManifest.xml ファイルでアプリがネイティブであることを宣言して、ネイティブ アプリの作成を開始するだけです。

NativeActivity を使用する Android アプリは、引き続き他のアプリからサンドボックス化された独自の仮想マシン上で実行されます。 したがって、JNI を介して Android フレームワーク API にアクセスすることも可能です。 ただし、センサー、入力イベント、アセットなどの特定のケースについては、NDK は JNI を介して呼び出さなくても使用できるネイティブ インターフェースを提供しています。 これらのサポートの詳細については、Android NDK ネイティブ API をご覧ください。

ネイティブ アクティビティを開発しているかどうかにかかわらず、従来の Android ビルドツールを使用してプロジェクトを作成することをお勧めします。 従来のツールでプロジェクトを作成すると、Android アプリを確実に正しい構造でビルドし、パッケージ化できます。

Android NDK では、以下のいずれかの方法でネイティブ アクティビティを実装できます。

  • native_activity.h ヘッダーは、NativeActivity クラスのネイティブ バージョンを定義します。 これにはネイティブ アクティビティの作成に必要なコールバック インターフェースとデータ構造が含まれます。 コールバックはアプリのメインスレッドで処理するため、コールバックの実装がブロックされてはなりません。 ブロックされると、コールバックが戻るまでメインスレッドから応答がなくなるため、 ANR(アプリが応答しない)エラーを受け取る可能性があります。
  • android_native_app_glue.h ファイルで、native_activity.h インターフェース上で構築された静的ヘルパー ライブラリを定義します。これにより別のスレッドが生成され、そこでコールバックやイベントループ内の入力イベントなどが処理されます。 これらのイベントを別のスレッドに移動することで、コールバックがメインスレッドをブロックする状況を回避できます。

実装を変更できる <ndk_root>/sources/android/native_app_glue/android_native_app_glue.c ソースも使用できます。

この静的ライブラリの使用方法の詳細は、ネイティブ アクティビティのサンプル アプリとそのドキュメントをご覧ください。 <ndk_root>/sources/android/native_app_glue/android_native_app_glue.h ファイルのコメントも併せてご確認ください。

native_activity.h インターフェースの使用

次の手順で native_activity.h インターフェースを使用してネイティブ アクティビティを実装します。

  1. プロジェクトのルート ディレクトリに jni/ ディレクトリを作成します。このディレクトリにはネイティブ コードのすべてが保存されます。
  2. ネイティブ アクティビティを AndroidManifest.xml ファイルに宣言します。
  3. アプリには Java コードが含まれていないため、android:hasCodefalse に設定します。

    <application android:label="@string/app_name" android:hasCode="false">
    

    アクティビティ タグの android:name 属性を NativeActivity に設定する必要があります。

    <activity android:name="android.app.NativeActivity"
                android:label="@string/app_name">
    

    : NativeActivity をサブクラス化できます。サブクラス化した場合、NativeActivity の代わりにサブクラスの名前を使用します。

    meta-data タグの android:value 属性で、アプリへのエントリ ポイント(C/C++ の main など)を含む共有ライブラリの名前を指定します。この際、ライブラリ名から lib 接頭辞と .so 接尾辞を省きます。

              <meta-data android:name="android.app.lib_name"
                android:value="native-activity" />
                <intent-filter>
                  <action android:name="android.intent.action.MAIN" />
                  <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
              </activity>
            </application>
          </manifest>
    
  4. ネイティブ アクティビティ向けのファイルを作成し、ANativeActivity_onCreate の変数で名前を指定した関数を実装します。ネイティブ アクティビティが開始されると、アプリはこの関数を呼び出します。 この関数は C/C++ の main に類似しており、ANativeActivity 構造へのポインターを受け取ります。これには、作成が必要なさまざまなコールバック実装への関数ポインターが含まれています。ANativeActivity->callbacks 内で、適切なコールバック関数ポインターをコールバックの実装に設定します。
  5. 使用する固有データのすべてのインスタンスのアドレスに ANativeActivity->instance フィールドを設定します。
  6. 開始時にアクティビティで実行したいその他の処理をすべて実装します。
  7. ANativeActivity->callbacks に設定したコールバックの残りを実装します。コールバックの呼び出し時の詳細については、アクティビティ ライフサイクルの管理をご覧ください。
  8. アプリの残りの部分を開発します。
  9. プロジェクトの jni/ ディレクトリに Android.mk file を作成し、ビルドシステム用にネイティブ モジュールを記述します。 詳細については、Android.mk をご覧ください。
  10. Android.mk ファイルを作成したら、ndk-build コマンドを使用してネイティブ コードをコンパイルします。
  11. $ cd <path>/<to>/<project>
    $ <ndk>/ndk-build
    
  12. 通常どおり Android プロジェクトをビルドし、インストールします。ネイティブ コードが jni/ ディレクトリにある場合、それらをビルドしてできた .so ファイルが、ビルド スクリプトによって自動的に APK にパッケージ化されます。
This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.