Java Native Interface(JNI)
JNI 是用來讓Java跟別種語言溝通的函式庫
Android中是讓Java及C之間溝通
分為Java Call C及C Call Java
Android Native Development Tools(NDK)
將C code包成.so檔,供Java利用
流程方法
藉由java撰寫native method,JNI即可在Java中呼叫C寫的程式
C的程式藉由NDK包成.so檔,就可以被JNI呼叫
//=============================================================
程式流程
1). (java) 撰寫native method,不需實做
2). 將寫好的.java檔,編成.class檔,再轉成.h檔
3). (C) 撰寫C程式碼,實做.h中的function標頭
3). 利用NDK將C程式碼轉成.so檔
4). (java) 利用JNI呼叫C的程式
//=============================================================
步驟
1).
(java) 撰寫native method,不需實做
native method前要加native
要load的.so檔是lib
cal_bmi_c.so,扣除掉前面的lib及後面的.so
method是calbmi,回傳是double的型態
從Java傳入使用者輸入的height, weight
[Bmi.java]
package com.jni;
public class Bmi {
public native double calbmi(double height, double weight);
static{
//要load的.so檔。去掉開頭的lib,及結尾的.so
System.loadLibrary("cal_bmi_c");
}
}
2).
將寫好的.java檔,編成.class檔,再轉成.h檔
Eclipse會自動編成.class檔
進入project的資料夾,新開jni資料夾
將編好的.h檔放在jni資料夾中
$ cd [project資料夾]
$ mkdir jni
$ cd jni
$ javah -jni -classpath [放置class的資料夾] [package].[class]
ex: javah -jni -classpath /home/qn_lo/develop/android/workspace/BmiJni/bin/classes com.jni.Bmi
3).
(C) 撰寫C程式碼,實做.h中的function標頭在jni資料夾新增C程式碼檔案
將.h檔的JNIEXPORT複製到C並實作
[com_jni_Bmi.h]
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_jni_Bmi */
#ifndef _Included_com_jni_Bmi
#define _Included_com_jni_Bmi
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jni_Bmi
* Method: calbmi
* Signature: (DD)D
*/
JNIEXPORT jdouble JNICALL Java_com_jni_Bmi_calbmi
(JNIEnv *, jobject, jdouble, jdouble);
#ifdef __cplusplus
}
#endif
#endif
[com_jni_Bmi.c]
#include
#include
JNIEXPORT jdouble JNICALL Java_com_jni_Bmi_calbmi
(JNIEnv *env, jobject obj, jdouble cheight, jdouble cweight)
{
double height,weight,bmi;
height=cheight/100;
weight=cweight;
bmi=weight/(height*height);
return bmi;
}
4).
撰寫NDK需要的Android.mk在jni資料夾中新增Android.mk
LOCAL_MODULE是編成的.so檔名
LOCAL_SRC_FILES是要編的C程式碼檔名
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cal_bmi_c
LOCAL_SRC_FILES := com_jni_Bmi.c
include $(BUILD_SHARED_LIBRARY)
5). 利用NDK將C程式碼轉成.so檔
a). 先到Android NDK下載NDK
b). 在project資料夾下新建libs的資料夾
如果有需要,可在Eclipse中在Project按右鍵reflesh
c). 在Eclipse的Project點右鍵[properties]
在[Builders]中new一個編譯器,選擇program
輸入Builder的Name,在Main標籤中,輸入Location及Working Directory
在Refresh標籤中,將Refresh resource upon completion勾選
並選擇Specific resource的路徑為project的libs
在Build Options標籤中
勾選Specify working set of relevant resource
並選擇Specify Resource路徑為Project的jni
d). 按下Build All的按鈕將C編成.so檔
6).
(java) 利用JNI呼叫C的程式在java要呼叫,[放JNI的class]().[native method]
new Bmi().calbmi(height, weight)
參考資料:
http://ironurbane.iteye.com/blog/425513
http://kitty.2y.idv.tw/~enijmax/linux/CLib_Jni.html