android JNI是连接android Java部分和C/C++部分的纽带,完整使用JNI需要Java代码和C/C++代码。其中C/C++代码用于生成库文件,Java代码用于引用C /C++库文件以及调用C/C++方法。
代码示例:(两种注册方式)
1,java部分:
package com.andy.jni;
public class JNI {
static {
System.loadLibrary("andy_jni");
}
public native int nadd(int num1,int num2);
public native String stringFromJNI();
}
2,C/C++部分:
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define NELEM(x) sizeof(x)/(sizeof(x[0]))
//方式一
extern "C" {
JNIEXPORT jstring JNICALL Java_com_andy_jni_JNI_stringFromJNI(JNIEnv* env,jobject thiz);
}
JNIEXPORT jstring JNICALL Java_com_andy_jni_JNI_stringFromJNI(JNIEnv* env,jobject thiz){
return env->NewStringUTF("I am come from JNI !");
}
//方式二
const char* JNIT_CALSS = "com/andy/jni/JNI";
static jint Java_com_andy_jni_JNI_nadd(JNIEnv* env, jobject obj,jint param1,jint param2){
return param1+param2;
}
static JNINativeMethod gMethods[] = {
{"nadd","(II)I",(void*)Java_com_andy_jni_JNI_nadd},
};
static jint registerNativeMethods(JNIEnv* env,const char* classname,JNINativeMethod* gMethods,jint gMethodsNum){
jclass clazz;
clazz = env->FindClass(classname);
if(clazz == NULL){
return JNI_FALSE;
}
if(env->RegisterNatives(clazz,gMethods,gMethodsNum) < 0){
return JNI_FALSE;
}
return JNI_TRUE;
}
static jint register_android_native_methods(JNIEnv *env){
return registerNativeMethods(env,JNIT_CALSS,gMethods,NELEM(gMethods));
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){
JNIEnv *env = NULL;
if(vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK){
printf("Error GetEnv\n");
return -1;
}
assert(env != NULL);
if(register_android_native_methods(env) < 0){
printf("register_android_native_methods\n");
}
return JNI_VERSION_1_4;
}
需要注意的是:
1)JNI C/C++部分的代码需要在android源代码树上进行编译,编译完成后我的做法是直接将生成的.so通过adb push方法上传到android虚拟机的/system/lib/目录下;
2)java代码可以在eclipse下直接编译且在虚拟机上执行;
编译JNI C/C++部分代码(在android内核源代码根目录下):
#make libhello_jni
之后在out/target/product/generic/system/lib/目录下生成libhello_jni.so
上传libhello_jni.so到android虚拟机:
#adb push out/target/product/generic/system/lib/libhello_jni.so /system/lib
注意:此时有可能出现Out of Memory的错误提示。当出现如上错误提示时,需要使用#adb remount重新加载一下就可以了。
另外,也有可能直接使用eclipse启动android虚拟机时出现上述错误且使用#adb remount也出现的情况,此时需要手动启动android虚拟机,如:#emulator -avd xxx -partition-size 128,之后在使用#adb push就可以了