JNI文件夹中一般包括Android.mk、native.cpp和其他.c/.h文件
Android.mk文件
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
#LOCAL_MODULE_TAGS := eng samples
LOCAL_MODULE_TAGS := optional
# This is the target being built.
LOCAL_MODULE:= libamtjni #这里是JNI库名,lib+名字+jni
# All of the source files that we will compile.
LOCAL_SRC_FILES:= \ #所要编译的源码 .c和.cpp文件
native.cpp \
amt_command.c
# All of the shared libraries we link against.
LOCAL_SHARED_LIBRARIES := \ #需要连接的共享库 libutils
# No static libraries.
LOCAL_STATIC_LIBRARIES :=
# Also need the JNI headers.
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
# No special compiler flags.
LOCAL_CFLAGS +=
# Don't prelink this library. For more efficient code, you may want
# to add this library to the prelink map and set this to true. However,
# it's difficult to do this for applications that are not supplied as
# part of a system image.
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
native.cpp文件
#include <utils/Log.h>
#include <stdio.h>
#include "jni.h"
#include <stdlib.h>
#define LOGD ALOGD
#define LOGE ALOGE
#define LOGI ALOGI
static jstring app_test(JNIEnv *env, jobject thiz) { FILE *fp = NULL; char serial_no_buffer_a[100 + 1]; char *usb_serial_no_file_path = "/amt/usb_serial"; memset( serial_no_buffer_a, 0, sizeof(serial_no_buffer_a) ); fp = fopen(usb_serial_no_file_path, "r");
if(NULL != fp)
{
//if( EOF != fscanf(fp, "%s", serial_no_buffer_a))
fread( serial_no_buffer_a, sizeof(serial_no_buffer_a) - 1, 1, fp ); if( feof(fp) )
{
LOGI( "Settings status read adb serial no ok and content is %s", serial_no_buffer_a );
}
else
{
LOGI("Settings status read fread error or file content length bigger then 100" );
}
fclose(fp);
}
else
{
LOGI("Settings status read fopen error or usb serial file not exist" );
LOGI("Settings status return default serial no T802");
strcpy( serial_no_buffer_a, "T802" );
} return env->NewStringUTF( serial_no_buffer_a );
} static const char *classPathName = "com/android/settings/deviceinfo/Native"; static JNINativeMethod methods[] = {
{"uni_serial_no_read", "()Ljava/lang/String;", (void*)uni_serial_no_read }, {"java文件中调用的函数名","(JNI函数参数类型)JNI函数返回值类型",(void*)jni函数名}
}; /*
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods)
{
jclass clazz; clazz = env->FindClass(className);
if (clazz == NULL) {
LOGE("Native registration unable to find class '%s'", className);
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
LOGE("RegisterNatives failed for '%s'", className);
return JNI_FALSE;
} return JNI_TRUE;
}
/*
* Register native methods for all classes we know about.
*
* returns JNI_TRUE on success.
*/
static int registerNatives(JNIEnv* env)
{
if (!registerNativeMethods(env, classPathName,
methods, sizeof(methods) / sizeof(methods[0]))) {
return JNI_FALSE;
} return JNI_TRUE;
}/*
* This is called by the VM when the shared library is first loaded.
*/
typedef union {
JNIEnv* env;
void* venv;
} UnionJNIEnvToVoid; jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
UnionJNIEnvToVoid uenv;
uenv.venv = NULL;
jint result = -1;
JNIEnv* env = NULL;
LOGI("JNI_OnLoad"); if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed");
goto bail;
}
env = uenv.env; if (registerNatives(env) != JNI_TRUE) {
LOGE("ERROR: registerNatives failed");
goto bail;
}
result = JNI_VERSION_1_4;
bail:
return result;
}
在java文件中,如果调用JNI的地方比较少,可以直接在调用的文件中加入
class Native { static { System.loadLibrary("编译的jni库名-lib");#如:编译的出来的名字叫 libtestjni ,此处名字为testjni }
static native JNI库中java的函数名;
}
如果需要很多文件调用或JNI文件中函数比较多,可以在java文件中新创建一个Native.java
package 包名;
public class Native {
static {
// The runtime will add "lib" on the front and ".o" on the end of
// the name supplied to loadLibrary.
System.loadLibrary("amtjni");
}
static native int add(int a, int b); static native 返回值类型 函数名(参数);#此处的函数名要和Native.cpp中的JNINativeMethod methods[]第一列函数名一致;
}
在其他java文件中就可以直接以Native.函数名 来调用