心胸决定格局,眼界决定境界...

使用RegisterNatives注册原生代码

在Android开发本地代码时,有两种方式,一种是使用javah生成头文件,然后编辑源代码,另一种不用生成头文件,直接编辑代码后,使用RegisterNatives方法进行注册,下面是一个Demo:

Java代码:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. package com.example.jnitest;  
  2.   
  3. public class TestJni {  
  4.     static {  
  5.         System.loadLibrary("Hello");  
  6.     }  
  7.     // static method  
  8.     public static native String test();  
  9.     // member method  
  10.     public native String test2();  
  11. }  


这里定义了两个native方法,test是静态方法,test2是成员方法。

 

使用C++实现两个方法:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. static jstring test(JNIEnv *env, jclass clz)  
  2. {  
  3.     LOGD("Hello1");  
  4.     return env->NewStringUTF("Hello1");  
  5. }  
  6.   
  7. static jstring test2(JNIEnv *env, jobject obj)  
  8. {  
  9.     LOGD("Hello2");  
  10.     return env->NewStringUTF("Hello2");  
  11. }  


实现了之后,需要注册两个方法

 

第一步:定义数据结构:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. // register methods:      
  2. JNINativeMethod内部数据结构

  3. typedef struct {
    const char* name;
    const char* signature;
    void* fnPtr;
    } JNINativeMethod;

    第一个变量name是Java中函数的名字。

    第二个变量signature,用字符串是描述了函数的参数和返回值

    第三个变量fnPtr是函数指针,指向C函数。

  4. static JNINativeMethod methods[] = {  
  5.         {"test", "()Ljava/lang/String;", (void*) &test},  
  6.         {"test2", "()Ljava/lang/String;", (void*) &test2}  
  7. };  

签名或者用javap生成


第二步:在JNI_OnLoad方法中,对方法进行注册:

 

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. int jniRegisterNativeMethods(JNIEnv* env,  
  2.                              const char* className,  
  3.                              const JNINativeMethod* gMethods,  
  4.                              int numMethods)  
  5. {  
  6.     jclass clazz;  
  7.     int tmp;  
  8.   
  9.     LOGD("Registering %s natives\n", className);  
  10.     clazz = env->FindClass(className);  
  11.     if (clazz == NULL) {  
  12.         LOGD("Native registration unable to find class '%s'\n", className);  
  13.         return -1;  
  14.     }  
  15.     if ((tmp=env->RegisterNatives(clazz, gMethods, numMethods)) < 0) {  //底层注册地方
  16.         LOGD("RegisterNatives failed for '%s', %d\n", className, tmp);  
  17.         return -1;  
  18.     }  
  19.     return 0;  
  20. }  
  21.   //修改的方法
  22. int registerNativeMethods(JNIEnv *env) {  //registerNativeMethods作为外在接口,调用jniRegisterNativeMethods
  23.     return jniRegisterNativeMethods(env, "com/example/jnitest/TestJni", methods, sizeof(methods) / sizeof(methods[0]));  
  24. }  
  25.   
  26. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {  //JNI_OnLoad 调用  registerNativeMethods
  27.   
  28.     JNIEnv* env = NULL;  
  29.     jint result = JNI_ERR;  
  30.   
  31.     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  32.         return result;  
  33.     }  
  34.   
  35.     if (registerNativeMethods(env) != JNI_OK) {  
  36.         return -1;  
  37.     }  
  38.   
  39.   
  40.     result = JNI_VERSION_1_4;  
  41.     LOGD("jni load start: %d", result);  
  42.   
  43.     return result;  
  44. }  

 

Android.mk:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
    1. LOCAL_PATH := $(call my-dir)  
    2. include $(CLEAR_VARS)  
    3. LOCAL_CFLAGS := -D__STDC_CONSTANT_MACROS  
    4. LOCAL_LDLIBS += -lc -lm -llog   
    5. LOCAL_SHARED_LIBRARIES += liblog libcutils libnativehelper  
    6. LOCAL_MODULE := Hello  
posted @ 2014-10-28 11:38  WELEN  阅读(1087)  评论(0编辑  收藏  举报