Android JNI 动态注册方法(JNI_OnLoad)
2016-09-06 10:44
971 查看
传统的关于android使用JNI调用C/C++程序,首先javah 生产头文件,然后拷贝头文件里面的方法到C文件中进行映射调用,由于这种方法生成的映射方法名不太规则也比较长,二呢是调用数据较慢;因此可以使用JNI动态注册方法的方式来解决这2问题。
** 1 在下面根目录下新建jni文件夹随便新建文件xxx.c;并且拷贝一份 Android.mk文件到jni下面,如:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_LDLIBS :=-llog LOCAL_PROGUARD_ENABLED:= disabled LOCAL_MODULE := nativenck #生产模块名称 LOCAL_SRC_FILES := com_exmple_ndk_NativeNCK.c#模块名称 include $(BUILD_SHARED_LIBRARY)
** 2 新建native的class,如NativeNCK:
public class NativeNCK { static{ System.loadLibrary("nativenck"); } public static native String getUrl(); public static native void setData(byte str[],int type); }
以上有2个方法需要调用C/C++层代码,方法名自定。
** 3 在xxx.c文件中首先导入常用包以及定义log:
#include <jni.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <assert.h> #include <Android/log.h> #define TAG "result" // 这个是自定义的LOG的标识 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)
** 4 添加JNINativeMethod方法:
static const JNINativeMethod gMethods[] = { {"getUrl", "()Ljava/lang/String;", (jstring*)getUrl}, {"setData","([BI)V",(void*)setData} };
ps:{“java代码中的方法名”,”方法([BI)V-表示传了byte数组和一个数字,并且为void方法;关于参数类型详细请看4-1”,
“这里是对C文件中的方法名写法:(返回类型*)+方法名”}
中间那个参数就是用来确定是否java端有传值过来,并且传值有规范写法如void function(Sting str,int a)方法在c中可以这么写: {“function”,”(Ljava/lang/String;I)”,”(void*)functionToJava”}
4-1图:
** 5 c文件中编写本地方法即可,如:
static jstring JNICALL getUrl(JNIEnv *env, jobject jobj){ return (*env)->NewStringUTF(env,"hello!Im C!"); } static JNICALL setData(JNIEnv *env, jobject jobj,jbyteArray zstr,jint zint){ LOGI("----setData----"); const char* str = (char*)zstr; LOGI("----INT=%d",zint); }
** 6 最后一步在JNI_Onload方法中注册,如:
static jclass myClass; #这里是java调用C的存在Native方法的类路径 static const char* const kClassName="com/exmple/ndk/NativeNCK"; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){ JNIEnv* env = NULL; //注册时在JNIEnv中实现的,所以必须首先获取它 jint result = -1; if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) //从JavaVM获取JNIEnv,一般使用1.4的版本 return -1; myClass = (*env)->FindClass(env, kClassName); if(myClass == NULL) { printf("cannot get class:%s\n", kClassName); return -1; } if((*env)->RegisterNatives(env,myClass,gMethods,sizeof(gMethods)/sizeof(gMethods[0]))<0) { printf("register native method failed!\n"); return -1; } printf("--------JNI_OnLoad-----"); return JNI_VERSION_1_4; //这里很重要,必须返回版本,否则加载会失败。 }
至此即可动态的注册方法到C中,不需要每次java层添加了新方法需要重新编译一次头文件。
ps:注意 注意 注意 …. 使用JNI动态注册的本地方法参数必带【JNIEnv *env,jobject *obj】否则会导致参数在C/C++中取值不正确。如:
void test(JNIEnv *env,jobject *obj,int arg1, int arg2,int arg3);
如果这里没写jobject *obj,导致本地拿到的值arg1没有,arg2赋值是arg1原来的值,arg3赋值是arg2原来的值。
相关文章推荐
- Android之JNI动态注册native方法和JNI数据简单使用
- Android JNI开发(1)--JavaVM和 JNIEnv 动态注册本地方法
- Android Studio Jni开发(三)Native方法动态注册
- Android Studio NDK 入门教程(8)--JNI动态注册本地方法
- Android JNI使用方法(“动态注册”)
- Android JNI使用方法(“动态注册”)
- Android JNI动态注册Native 方法(实现IDA中改名)
- JNI_OnLoad ()注册函数使用方法
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- Android 4.4.2 动态添加JNI库方法记录 (一 JNI库层)
- Android: JNI动态注册
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- 安卓 jni 开发之 native 方法的动态注册
- 安卓实战开发之JNI从小白到伪老白深入了解JNI动态注册native方法及JNI数据使用
- Android Dalvik虚拟机JNI方法的注册过程分析
- android — JNI注册方法说明
- android 动态注册JNI函数过程源码分析
- JNI_onLoad 动态注册函数