2013年2月19日火曜日

[Android]JNIってどうやるの

30分で使いたい人向けにいかサイトを参考に要点抜き出すよ
AndroidでJNIを使う方法



1.Android側作る
例だとTextViewに表示するだけでつまらないのでボタン押したら表示にする
とりあえずマネージャ
package com.hoge.jnitest
public class JniManager {
 /* jni load lib*/
 static {
  System.loadLibrary("JNItestNative");
 }
 /* jni native method*/
 public native String getTestStringFromNative();
}

次にActivity
package com.hoge.jnitest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class JniTestActivity extends Activity {
 private View jniButton;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  final JniManager jm = new JniManager();

  setContentView(R.layout.activity_jni_test);

     jniButton = (Button)findViewById(R.id.jniButton);
     jniButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
             /* call jni method */
             String strText = jm.getTestStringFromNative();
             /* set jni text */
             TextView jniText = (TextView)findViewById(R.id.jniText);
             jniText.setText(strText);
            }
        });
 }
}

こんなButtonとTextViewを適当に追加
    <TextView
        android:id="@+id/jniText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/jniButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:text="@string/jni_button" />


これでビルドとおったら次へどうぞいってくだしぃ。
ワークスペースのbin\classes\com\hoge\jnitest下にクラスファイルできてるの確認しといてね

2.Jniヘッダ作る
JDKについてくるjavahをこんな感じに使うよ
javah -classpath bin -d jni <jni native methodを定義とかしてるクラス>

今回だと
cd <ワークスペース>
javah -classpath bin -d jni com.hoget.JniManager

注意点的なあれで、Eclipce4.2だとbin下のフォルダ階層違うせいかできないから、
bin\classes\comを
bin\comにコピーしてやってくだしぃ。
クラスパスはclasspathオプションで指定することで別フォルダでも行けるらしいです。
javah -classpath bin\classes -d jni com.hoget.JniManager

出来るとワークスペースにJniフォルダができて、
その中にヘッダがある

3.Jni側つくる
external下にlibJNItestNativeフォルダ作る
2で作ったヘッダコピー

makeファイルとcソース書くよ

Android.mk
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
    getTestStringFromNative.c

LOCAL_C_INCLUDES :=     \
    $(JNI_H_INCLUDE)        \

LOCAL_MODULE  := libJNItestNative

LOCAL_PRELINK_MODULE := false

include $(BUILD_SHARED_LIBRARY)


getTestStringFromNative.c
中身の関数名はヘッダからこぴってくる
#include "com_hoge_JniManager.h"

JNIEXPORT jstring JNICALL Java_com_hoge_JniManager_getTestStringFromNative
  ( JNIEnv *env, jobject obj )
{
    return (*env)->NewStringUTF(env, (char *)"from Native Code String");
}

ビルド:
cd external\libJNItestNative
mm

成果物:
out/target/product/generic/system/lib/

置き場所:
#adb push libJNItestNative.so /system/lib

system下がreadonryだったらmmじゃなくてフルビルド
mmでエラーチェックしてからのほうが効率いいかも。

----
追記:systemパーティションをRWでリマウントするんだったらこれ。
リマウント対策がされてない限りこれでpush出来るようになる
adb shell mount -o rw,remount /system
---
追記2:javahはJDKインストールすると付いてくる
C:\Program Files\Java\jdk1.7.0_11\binみたいなところにあると思うので、
各自PATH通しましょう

0 件のコメント:

コメントを投稿