在这里NDK通过JNI调用c通常有两种方法,一种就是用javah编译出java的native方法,之后在c实现,另一种就是用RegisterNatives方法进行native方法的注册,再调用。。
鉴于代码好管理和方便查看我就采用第二种方法
一、我先在java端写native方法,再将动态链接库加载到程序中
public class UUIDNDK
{
static
{
System.loadLibrary("UUIDDemo");
}
public native String getUUID();
}
二、在c端先会将native方法放入一个JNINativeMethod映射数组里面
static JNINativeMethod gMethods[] = { { "getUUID", "()Ljava/lang/String;",(void*) getUUID }, };
a.”getUUID”是java端的native方法.
b.”()Ljava/lang/String;”是java端native代码参数和返回值的描述
c.(void *)getUUID就是c端的实现函数.
三、再重写JNI_OnLoad函数,当java端执行System.loadlibrary()时就会执行JNI_OnLoad()函数
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("GetEnv failed");
return JNI_ERR;
}
//注册本地方法
if (registerNativeMethods(env, CLASS_PATH_NAME, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) != JNI_TRUE) {
LOGE("ERROR: registerNatives failed");
return JNI_ERR;
}
return JNI_VERSION_1_4;
}
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);
env->DeleteLocalRef(clazz);
return JNI_FALSE;
}
env->DeleteLocalRef(clazz);
return JNI_TRUE;
}
四、而当VM释放该C组件时,则会呼叫JNI_OnUnload()函数来进行善后清除动作
void JNI_OnUnload(JavaVM* vm, void* reserved)
{
LOGI("JNI_OnUnLoad!");
JNIEnv *env;
jclass cls;
clearMemery();//释放程序中申请的内存
if (vm->GetEnv((void **) &env, JNI_VERSION_1_4))
return;
cls = env->FindClass(CLASS_PATH_NAME);
env->UnregisterNatives(cls);
return;
}
五、编写和java native方法对应C端的函数
jstring getUUID(JNIEnv *env, jclass thiz) {
LOGI("getUUID......");
return converchartojstring(env, "");
}
六、完成