基本プログラムねたは読まれないのでどうかと思うが
覚え書きと考えてください
Ubuntu上でAndroid SDKからC言語の関数を呼ぶ必要がありNDKについて学んだ。
基本的にはこれ
http://www.kkaneko.jp/rinkou/js/andk.html
目的もなく学び続けるのは辛いのでまず
Androidのクラス(JAVA)に
String okawapos(int pos);
という関数を作り,
この関数をjavaでなくCで実装することを課題とした。
中身は何でもいいが、今回は
"Hello, World! %d okawa kouji" を返すこととする。%dはもちろんposのこと。
つまりokawapos(3)で"Hello, World! 3 okawa kouji"を返す。
まずECLIPSEで開発環境を作ることから説明する。
まずNDKをダウンロード
https://developer.android.com/tools/sdk/ndk/index.html
これを解凍してホームにおく。
これでファイル配置は
/home/kokawa2003/android-ndk-r10/build
/doc
.....
となる。
次に/home/kokawa2003/android-ndk-r10にパスを通す。
具体的には
/home/kokawa2003/.bashrcに
export PATH=$PATH:~/android-ndk-r10
と書く。
ここで再起動
ndk-buildが使えるのを確認。
$ ndk-build
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
/home/kokawa2003/android-ndk-r10/build/core/build-local.mk:148: *** Android NDK: Aborting . Stop.
多分こんな結果。
パスがとおったら早速サンプルをビルドしてみる
たとえば
$ cd /home/kokawa2003/android-ndk-r10/samples/hello-jni/jni
$ ndk-build
結果はこれ
Android NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 3 in /home/kokawa2003/android-ndk-r10/samples/hello-jni/AndroidManifest.xml
[armeabi-v7a] Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi-v7a/gdbserver
[armeabi-v7a] Gdbsetup : libs/armeabi-v7a/gdb.setup
[armeabi] Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver
[armeabi] Gdbsetup : libs/armeabi/gdb.setup
[x86] Gdbserver : [x86-4.6] libs/x86/gdbserver
[x86] Gdbsetup : libs/x86/gdb.setup
[mips] Gdbserver : [mipsel-linux-android-4.6] libs/mips/gdbserver
[mips] Gdbsetup : libs/mips/gdb.setup
[armeabi-v7a] Install : libhello-jni.so => libs/armeabi-v7a/libhello-jni.so
[armeabi] Install : libhello-jni.so => libs/armeabi/libhello-jni.so
[x86] Install : libhello-jni.so => libs/x86/libhello-jni.so
[mips] Install : libhello-jni.so => libs/mips/libhello-jni.so
出力は
/home/kokawa2003/android-ndk-r10/samples/hello-jni/libs/
にある。
libs/armeabi-v7a/libhello-jni.so
libs/armeabi/libhello-jni.so
libs/x86/libhello-jni.so
libs/mips/libhello-jni.so
の4ファイルあれば正解。
ここで次にANDROID SDKでビルドかECLIPSEに取り込んでビルドか
どちらかでANDOIDアプリが起動するのを確認。
表示は
Hello from JNI ! Compiled with ABI armeabi-v7a
みたいな文字列になるハズ。(最後のarmeabi-v7a だけ環境で変わる)
ここでTIPとしてはABIという言葉についての説明
ABIとはApplication Binary Interfaceのこと
要するにABIが同じとは実行ファイルがバイナリレベルで互換である(動作する)ことを指す
この場合armeabi-v7a、armeabi、x86、mipsのCPU向けのファイルができている
この内android一般がarmeabiとなる。
さて次にjniを自作する方法
まずandroid appを作る。
app名:hello3
パッケージ名:com.example.hello3
のアプリの
クラス名: MainActivity
に
関数名:String okawapos(int pos);
を作るとする。
まずjniを作る。
hello3にサブフォルダjniを作る。
中身は2ファイル
hello.c
#include <string.h>
#include <jni.h>
jstring
Java_com_example_hello3_MainActivity_okawapos( JNIEnv* env, jobject thiz,jint pos )
{
char buff[256];
sprintf(buff,"Hello, World! %d okawa kouji\n",pos);
return (*env)->NewStringUTF(env, buff);
}
この関数だが
jstring Java_com_example_hello3_MainActivity_okawapos( JNIEnv* env, jobject thiz,jint pos )
が
javaの
String okawapos(int pos);
のCの対応関数となる。
まず名前 com_example_hello3_MainActivity_okawapos
これは"パッケージ名_クラス名_関数名"の意味。 ただしパッケージの.は_に置き換える
だから
String okawapos();
なら
jstring Java_com_example_hello3_MainActivity_okawapos( JNIEnv* env, jobject thiz)
となる。次に引数は
string->jstring
int ->jint
みたいな関係で引数の最初
JNIEnv* env, jobject thiz
は固定だと考えることにする。
もうひとつのファイルは
Android.mkで中身は
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.c
include $(BUILD_SHARED_LIBRARY)
これでlibhello.soが出力される。ただしそれにはちょっと設定する必要あり
まずプロジェクト名hello3を右クリックし
Convert to a C/C++ Project (Adds C/C++ Nature)
実行、次に
Makefile プロジェクトの他のツールチェーン
を選ぶ。これで完了
さらにプロジェクト名hello3を右クリックし
propertyのメニュー
C/C++ Build ー>Builder Settingsー>build command
/home/kokawa2003/android-ndk-r10/ndk-build
さらに
C/C++ Generalー>Paths and Symbolsー>Includes->GNU C
/home/kokawa2003/workspace/Hello3/jni
/home/kokawa2003/android-ndk-r10/platforms/android-19/arch-arm/usr/include
/home/kokawa2003/android-ndk-r10/platforms/android-19/arch-mips/usr/include
/home/kokawa2003/android-ndk-r10/platforms/android-19/arch-x86/usr/include
/usr/lib/jvm/java-7-oracle/include
/home/kokawa2003/android-ndk-r10/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.6/include
/home/kokawa2003/android-ndk-r10/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.6/include-fixed
と入れる
最後にjavaコード
public class MainActivity extends ActionBarActivity
に
public native String okawapos(int pos);
static {
System.loadLibrary("hello");
}
の宣言追加
コードは例えば
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = new TextView(this);
tv.setText( okawapos(3) );
setContentView(tv);
}
これでうまくビルドが通れば
"Hello, World! 3 okawa kouji"
が表示される