Androidで動く携帯Javaアプリ作成入門
Androidで動く携帯Javaアプリ作成入門(15)

Android NDKでJNIを使用してアプリを高速化するには


株式会社イーフロー
緒方聡
2010/3/17

ファイルやライブラリの情報を定義する「Android.mk」

 Android.mkは、$( APP_PROJECT_PATH)/jni/にあり、ファイルやライブラリの情報を定義します。下記は、今回使用するAndroid.mkの内容です。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := FireEffect
LOCAL_SRC_FILES := FireEffect.c
LOCAL_LDLIBS := -llog
LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)
- PR -

LOCAL_PATH

 これは、Android.mkの最初に定義しなければなりません。my-dirマクロで現在のディレクトリを指定しています。

include $(CLEAR_VARS)

 LOCAL_PATHを除くLOCAL_xxxの定義をクリーンアップします。複数のライブラリを使用する場合などに、「先に読み込んだAndroid.mkのLOCAL_xxxの値が不本意に使用されてしまう」という障害を防ぐためにも、定義しておくことを強く推奨します。

LOCAL_MODULE

 モジュール名を指定します。この名前はユニークでなければならず、スペースを含んではいけません。NDKのビルドシステムは、ここで与えられた名前にプレフィックスとサフィックスを自動的に付与します。

 今回の場合は、「libFireEffect.so」という共有ライブラリを生成します(もしここで、「libFireEffect」という名前を指定した場合、生成される共有ライブラリは「liblibFireEffect.so」ではなく、例外的に「libFireEffect.so」となることに注意してください)。

LOCAL_SRC_FILES

 C/C++のソースリストを指定します。ヘッダファイルは含めません。C++ソースファイルの拡張子は.cppがデフォルトです。

LOCAL_LDLIBS

 自身のライブラリにリンクするライブラリを指定します。今回は、ネイティブでもandroid.util.Log相当のログが出力できるlogライブラリをリンクしています。

LOCAL_ARM_MODE

 より高速なarmモードでコンパイルするように指定します。

include $(BUILD_SHARED_LIBRARY)

 共有ライブラリを作成する際に指定します。静的ライブラリを作成する場合は、BUILD_STATIC_LIBRARYを指定します。

定義一覧

 上記を含むすべての定義を、以下の表にまとめておきますので、参考にしてください。

表5 Android.mkの定義
定義 説明
LOCAL_PATH パスを指定(最初に定義しなければならない)
LOCAL_MODULE モジュール名を指定
LOCAL_SRC_FILES ソースファイルを指定
LOCAL_CPP_EXTENSION C++の拡張子を指定(デフォルトは.cpp)
LOCAL_C_INCLUDES  
LOCAL_CFLAGS Cソースのコンパイルフラグを指定
LOCAL_CXXFLAGS C++ソースのコンパイルフラグを指定
LOCAL_CPPFLAGS C/C++両方のソースのコンパイルフラグを指定
LOCAL_STATIC_LIBRARIES BUILD_STATIC_LIBRARYで指定したモジュールでリンクしたいものを指定。共有ライブラリ作成時のみ指定可能
LOCAL_SHARED_LIBRARIES このモジュールが実行時に参照する共有ライブラリを指定
LOCAL_LDLIBS ライブラリビルド時に必要な追加リンクフラグ
LOCAL_ALLOW_UNDEFINED_SYMBOLS undefined symbolエラーを発生させたくない場合はtrueを指定
LOCAL_ARM_MODE armかthumbを指定(デフォルトはthumb)
include $(CLEAR_VARS) LOCA_PATH以外のLOCAL_で始まる定義をクリア
include $(BUILD_SHARED_LIBRARY) 共有ライブラリ作成を指示
include $(BUILD_STATIC_LIBRARY) 静的ライブラリ作成を指示
$(TARGET_ARCH) ターゲットのアーキテクチャを返す
$(TARGET_PLATFORM) ターゲットのプラットフォームを返す
$(TARGET_ARCH_ABI) CPUとABIの名前を返す
$(TARGET_ABI) 「$(TARGET_PLATFORM)
-$(TARGET_ARCH_ABI)」という値を返す

JNIを使ったAndroidアプリを動かすには


ネイティブコードのコンパイル

 Application.mkとAndroid.mkの準備ができたら、コンパイルを行います。コンパイルは、NDKホームディレクトリで以下のように入力します。

make APP=LiveWallpaperSampleWithJNI -B

 「APP=」以降には、「apps」ディレクトリに配置されているプロジェクトを指定します。makeに渡せるオプションは以下の通りです。

表6 NDKのmakeオプション
オプション 説明
APP= プロジェクト名を指定(必須)
V=1 ビルド時に詳細な出力を行う
-B 必ずリビルドする

 今回のサンプルだと、ビルド時に以下のようなメッセージが表示されます。

Android NDK: Application LiveWallpaperSampleWithJNI targets platform 'android-7'

 Live Wallpaperはandroid-7の機能であるため、defalut.propertiesに「android-7」と定義されています。一方Android NDK r1は、android-4までしかサポートしていないため、コンパイルが実行できません。

 これを回避するには、NDKでコンパイルする際には、一時的にdefault.properties内部のandroid-7をandroid-4にします。

 コンパイルに成功すると、apps/<project>/libs/armeabiにライブラリが生成されます。

アプリのパッケージング

 ネイティブライブラリを.apkにパッケージングするのに、特別な作業は必要ありません。プロジェクトをビルドすれば、自動的にネイティブライブラリがパッケージングされ、特別なことをせずに実行可能です。

Android NDK/JNIを使用する際の注意点

 AndroidでJNI(NDK)を使用する場合、知っておくべきことがいくつかあるので、最後にお話しします。

Cのサポート

 AndroidのCライブラリは「libc」ではなく「Bionic」というAndroid独自の実装です。この実装はANSI C準拠ではないため、ANSI Cにあるはずのヘッダファイルや関数がないことがあります。

 NDKは、Cライブラリを自動でリンク対象にするため、LOCAL_LDLIBSにCライブラリを指定する必要はありません。

 また、<math.h>のために「-lm」を指定する必要はありません。NDKはpthreadを標準でサポートするため、「LOCAL_LDLIBS := -lpthread」は必要ありません。ただし、pthread_cancelはサポートされないので、注意してください。リアルタイム拡張も同様なので、「-lrt」も必要ありません。

 加えて、ワイドキャラクタがサポートされていません。ヘッダファイル <linux/*.h>および<asm/*.h>は、将来的に変更される可能性があるため、これらを直接インクルードすることは推奨されません。

C++のサポート

 極めて小さなC++のAPIがサポートされます。提供されるヘッダファイルは以下の通りです。

  • <cstddef>
  • <new>
  • <utility>
  • <stl_pair.h>

 また、これらは完全なものではなく、標準として必要なすべての定義を含んでいません。特に、C++の例外とRTTIは使用できません

 NDKは、C++ライブラリを自動でリンク対象にするため、LOCAL_LDLIBSに「-lstdc++」を指定する必要はありません。

Android固有のログサポート

 <android/log.h>は、ネイティブコードからカーネルにログメッセージを送るために使用できる定義を含んでいます。以下にリストします。

表7 ログの定義
関数名 説明
__android_log_write 文字列出力
__android_log_print 文字列出力(printf相当)
__android_log_vprint 文字列出力(va_list版)
__android_log_assert アサート

 JavaのLogクラスと同じく、プライオリティによる出力制御、タグ指定が行えます。

@IT関連記事


Androidアプリで高速描画チューニングをするコツ
インタビュー特集:Google直伝!(1) Googleのさまざまなサービスを使いこなすコツをグーグル担当者に聞くインタビュー。初回は日本で端末販売がせまるAndroidについて
リッチクライアント & 帳票」フォーラム 2009/4/21
HTML+JavaScriptでiPhone/Androidアプリを作る
Web技術でネイティブアプリを作れるTitanium(1) 
iPad/iPhone VS Androidに戸惑っているWebデザイナ/開発者のためにオープンソースの開発ツールを紹介します
JNIより簡単にJavaとC/C++をつなぐ「JNA」とは
組み込みにも役立つJavaとネイティブコードの橋渡し 
JavaからC/C++のコードを呼び出す技術の1つとして、JNAライブラリを徹底解説し、6つのマッピング方法を紹介します
Java Solution」フォーラム 2009/12/14
組み込みJavaのいま−携帯電話、Blu-rayに続くモノ
特集:Javaは組み込みに“不向き”は本当か?
 携帯電話やBlu-rayなどでJavaの利用は着実に広がりつつある。あらためて組み込み分野でのJavaの可能性を考えてみよう
OpenGL ESプログラミングで本格3D描画体験
BREWアプリケーション開発入門(7)
 OpenGL ESによる3Dグラフィックス描画プログラミングに挑戦! 投影、ライトなどの各種要素を理解し、立方体の描画を行ってみよう
OpenGL ESが大変な3Dアプリ開発を楽にするUnity
ここが大変だよiPhone開発(最終回) iPhoneゲーム開発に必須のOpenGL ES。そのコーディングに手こずっている方に有用なツールを紹介し簡単なサンプルを作成します

ケータイ分野以外の組み込みデバイス開発の現場でも注目を集めている「Android」。組み込みデバイスへの適用からアプリケーション開発、イベントレポート、ニュースなどAndroidに関するさまざまな技術情報・最新動向をお届けします!

1-2-3

 Index
第15回 Android NDKでJNIを使用してアプリを高速化するには
  Page1
Android NDK最新版でOpenGL ES 2.0をサポート
そもそも、JNIってAndroidに必要なの?
コラム 「難しいJNIのメモリ管理に対する戦略」
アプリのどこが重いのかを調べ、ネイティブ化すると
  Page2
AndroidアプリのソースコードにJNIを組み込むには?
コラム 「Dalvik VMのクラスローダは要注意」
Android NDKのセットアップ
Android NDKの中身はどうなっている?
アプリの定義を記す「Application.mk」
コラム 「Android NDKが備える5つのマクロ」
Page3
ファイルやライブラリの情報を定義する「Android.mk」
JNIを使ったAndroidアプリを動かすには
Android NDK/JNIを使用する際の注意点

Androidで動く携帯Javaアプリ作成入門 バックナンバー 連載インデックスへ»


ご意見、ご感想は Smart&Social 会議室へどうぞ


 Smart&Social フォーラム トップページへ


TechTargetジャパン

Smart & Social フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

キャリアアップ

@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る
- PR -

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH