JNI 是Java Native Interface。
Java Native Interface (JNI)標準成爲java平臺的一部分,
它允許Java代碼和其他語言寫的代碼進行交互。
JNI 是本地編程接口。它使得在 Java 虛擬機 (VM) 內部運行的 Java 代碼
能夠與用其它編程語言(如 C、C++ 和彙編語言)編寫的應用程序和庫進行互操作。
下面就是我在 Android 環境中一個Test JNI 的代碼。
1.
// TestNativeApi.java
// Native程序,編譯成jar包形式,被上層java應用調用。
// static 函數中調用 android System.loadLibrary() 來調用 .so 庫,
// loadLibrary()會判斷 .so庫的類型,如果是jni庫,則會調用 .so庫中的 JNI_OnLoad()函數來註冊jni interface.
package com.me.test;
import android.util.Log;
public final class TestNativeApi {
static {
try {
System.loadLibrary("itest_jni");
} catch (UnsatisfiedLinkError e) {
Log.d("itest_jni", "itest jni library not found!");
}
}
/**
* This class is uninstantiable.
*/
private TestNativeApi() {
// This space intentionally left blank.
}
public native static int apiFunction();
}
// Android.mk for TestNativeApi.java
// 通過函數 BUILD_JAVA_LIBRARY 編譯成jar.
# Build com.me.test.jar
# ============================================================
test_dirs := /
./test/java/com/me/test
test_src_files := $(call all-java-files-under,$(cm_dirs))
# ==== the library =========================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(test_src_files)
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core framework
LOCAL_MODULE := com.me.test
include $(BUILD_JAVA_LIBRARY)
2.
// TestInternalApi.cpp
// JNI interface class, JNI_OnLoad()函數在.so被load的時候調用
// JNI interface function中可以調用底層的 C++/C函數控制硬件等
#define LOG_TAG "itest_jni"
#include
#include
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "scm_dbus_utils.h"
#define INTERNALAPI_PKG_NAME "com/me/test/TestNativeApi"
using namespace android;
static jint test_TestInterAPI_Func(JNIEnv* env, jobject clazz)
{
jint ret = (jint)0;
LOGD("call /"%s/"", __FUNCTION__);
return ret;
}
/*
* JNI registration.
*/
static JNINativeMethod gTestInterApiMethods[] = {
{ "apiFunction", "()I", (void *)test_TestInterAPI_Func }
};
int register_com_me_test_TestInternalApiNative(JNIEnv *env)
{
return AndroidRuntime::registerNativeMethods(env, INTERNALAPI_PKG_NAME, gTestInterApiMethods, NELEM(gTestInterApiMethods));
}
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
jint result = -1;
LOGD("TestInteralApi JNI loaded");
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("GetEnv failed");
goto bail;
}
assert(env != NULL);
if (register_com_me_test_TestInternalApiNative(env) < 0) {
LOGE("TestInternalApi native registration failed");
goto bail;
}
result = JNI_VERSION_1_4;
bail:
return result;
}
// Android.mk for TestInternalApi.cpp
// 通過函數 BUILD_SHARED_LIBRARY 編譯成 .so .
include $(CLEAR_VARS)
ifeq ($(TARGET_ARCH), arm)
LOCAL_CFLAGS += -DPACKED="__attribute__ ((packed))"
else
LOCAL_CFLAGS += -DPACKED=""
endif
LOCAL_SRC_FILES:= /
TestInternalApi.cpp
LOCAL_C_INCLUDES += /
$(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := /
libandroid_runtime /
libnativehelper /
libcutils /
libutils /
libdvm
LOCAL_MODULE:= libitest_jni
include $(BUILD_SHARED_LIBRARY)
endif