Android: NDKを使ってみました

NDK(Android Native Development Kit)を使ってみました。

・NDKとは?

参考:What is the NDK?
http://developer.android.com/sdk/ndk/overview.html

The Android NDK is a toolset that lets you embed components that make use of native code in your Android applications.

参考:General notes
http://developer.android.com/sdk/ndk/index.html

By default, code is generated for ARM-based devices, but you can add x86 to your APP_ABI definition in your Application.mk file to build for x86 platforms. For example, the following line instructs ndk-build to build your code for three distinct ABIs:

 APP_ABI := armeabi armeabi-v7a x86

参考:Development tools
http://developer.android.com/sdk/ndk/overview.html#tools

The NDK includes a set of cross-toolchains (compilers, linkers, etc..) that can generate native ARM binaries on Linux, OS X, and Windows (with Cygwin) platforms.

=>
$ cd /usr/local/android-ndk-r6 <= NDKをインストールしたディレクトリ
$ ls toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/libexec/gcc/arm-linux-androideabi/4.4.3
cc1  cc1plus  collect2
$ ls platforms/android-3/arch-arm/usr/lib/
crtbegin_dynamic.o  libc.a    liblog.so  libstdc++.a     libthread_db.so
crtbegin_static.o   libc.so   libm.a     libstdc++.so    libz.so
crtend_android.o    libdl.so  libm.so    libthread_db.a
$ file platforms/android-3/arch-arm/usr/lib/libc.so
platforms/android-3/arch-arm/usr/lib/libc.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped

It provides a set of system headers for stable native APIs that are guaranteed to be supported in all later releases of the platform:

  * libc (C library) headers
  * libm (math library) headers
  .......................................................

・ダウンロード

developer.android.comからandroid-ndk-r6-linux-x86.tar.bz2をダウンロードして展開。
http://developer.android.com/sdk/ndk/index.html

# cd /usr/local
# tar xvf android-ndk-r6-linux-x86.tar.bz2
# ls android-ndk-r6
GNUmakefile  build               ndk-build  platforms  tests
README.TXT   docs                ndk-gdb    samples    tmp
RELEASE.TXT  documentation.html  ndk-stack  sources    toolchains

・サンプル(hello-jni)をコンパイルしてシェアードライブラリを作成

参考:
http://developer.android.com/sdk/ndk/overview.html#samples

$ cp /usr/local/android-ndk-r6/samples/hello-jni .
$ cd hello-jni

$ cat jni/hello-jni.c    <= 注) スペース上、オリジナルであったコメントは削除してあります。
#include 
#include 
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    return (*env)->NewStringUTF(env, "Hello from JNI !");
}

$ cat src/com/example/hellojni/HelloJni.java <= 注) スペース上、オリジナルであったコメントは大方、
                          削除してありますが、コメントは参考になります。
package com.example.hellojni;

import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;

public class HelloJni extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        TextView  tv = new TextView(this);
        tv.setText( stringFromJNI() );
        setContentView(tv);
    }
    /* A native method that is implemented by the
     * 'hello-jni' native library, which is packaged
     * with this application.
     */
    public native String  stringFromJNI();
    public native String  unimplementedStringFromJNI();
    static {
        System.loadLibrary("hello-jni");
    }
}

$ /usr/local/android-ndk-r6/ndk-build  <= ndk-buildコマンドを実行してシェアードライブラリをクロスコンパイル
Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
Gdbsetup       : libs/armeabi/gdb.setup
Compile thumb  : hello-jni <= hello-jni.c
SharedLibrary  : libhello-jni.so
Install        : libhello-jni.so => libs/armeabi/libhello-jni.so
$ file libs/armeabi/libhello-jni.so
libs/armeabi/libhello-jni.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
$ nm ./obj/local/armeabi/libhello-jni.so
................................
000002dd T Java_com_example_hellojni_HelloJni_stringFromJNI  <=これがライブラリ関数
00001324 a _DYNAMIC
000013ac a _GLOBAL_OFFSET_TABLE_
         U __aeabi_unwind_cpp_pr0
000013b8 A __bss_end__
000013b8 A __bss_start
000013b8 A __bss_start__
000013b8 D __data_start
000013b8 A __end__
00000324 A __exidx_end
0000031c A __exidx_start
000013b8 A _bss_end__
000013b8 A _edata
000013b8 A _end
[user01@lx02 hello-jni]$

・上記ライブラリを使うAndroidアプリのサンプルをEclipseでビルドして実行

[Eclipse] => [ファイル] => [新規] => [Androidプロジェクト] =>
 [プロジェクト名] : hello-jni (例)
 [外部ソースからプロジェクトを作成]: ここで上記hello-jniのパスを指定
=> [完了]
これでプロジェクトの作成は完了し、プロジェクトhello-jniを[実行]あるいは[デバッグ]するとhello-jni.apkができる。
$ ls -l bin/hello-jni.apk
-rw-rw-r--. 1 user01 user01 80906 8月 29 17:00 2011 bin/hello-jni.apk