Android NDK系列(6) — 动态注册native方法
来源:互联网 发布:淘宝怎么下架商品 编辑:程序博客网 时间:2024/06/16 02:35
我在博客上发表一些我的NDK学习心得,希望对大家能有帮助。 这一篇我们讲述如何动态注册native方法
介绍
首先,之前写的文章中通过一个简单的例子来使用了一下NDK,实现了从Native中调用Java方法。
下面,我们要介绍的是实现动态绑定native方法来破除命名限制。
问题
在静态注册的情况,所有的方法都是有固定的方法名:Java_<包名> <类名> <方法名>,这种情况下,调用一个方法比较繁琐,同时也有命名限制,所以使用动态绑定来解决这个问题。
实践
首先,还是老样子,加载so,定义native方法
public class MyJni { static { System.loadLibrary("myjni"); } public native void nativePrint(); public native int nativeCount(int a, int b); public MyJni() { Log.d("123", "Load MyJni nativePrint & nativeCount"); nativePrint(); int a = nativeCount(1,2); Log.d("123", a+""); }}
为了在程序初始化的时候进行方法的动态注册,当so被加载时就会调用JNI_OnLoad函数,需要重写JNI_OnLoad方法,在该方法中注册
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){ JNIEnv* env = NULL; jint result = -1; if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE("GetEnv failed!"); return -1; } //=========================================== assert(env != NULL); if (!registerNatives(env)) // 注册本地方法 { return -1; } //=========================================== /* success -- return valid version number */ result = JNI_VERSION_1_4; return result;}
调用registerNatives进行注册,其中需要指定注册的类信息,这样才能够获取其jclass对象
/** 为所有类注册本地方法*/static int registerNatives(JNIEnv* env) { const char* kClassName = "com/example/qiuyu/testhellojni/MainActivity";//指定要注册的类 return registerNativeMethods(env, kClassName, gMethods, sizeof(gMethods) / sizeof(gMethods[0]));}
调用registerNativeMethods,使用RegisterNatives进行注册
/** 为某一个类注册本地方法*/static int registerNativeMethods(JNIEnv* env , const char* className , JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = (*env)->FindClass(env, className); if (clazz == NULL) { return JNI_FALSE; } if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE;}
需要定义gMethods JNINativeMethod数组,实际就是修改指针指向执行的函数,从而实现方法注册
// 该结构表示一个Java本地方法与native层的c方法的映射 typedef struct { char *name; // Java本地方法名称 char *signature; // Java本地方法签名 void *fnPtr; // c函数指针 } JNINativeMethod; /*** Table of methods associated with a single class.*/static JNINativeMethod gMethods[] ={ {"nativePrint", "()V", (void*)native_Print }, {"nativeCount", "(II)I", (void*)native_Count },};// 实际执行函数void native_Print(JNIEnv * env, jobject thiz) { LOGE("native_Print");}jint native_Count(JNIEnv * env, jobject thiz, jint a, jint b) { return a+b;}
最终执行结果如下:
07-05 04:52:17.739 23202-23202/com.example.qiuyu.testhellojni D/123: Load MyJni nativeSetup07-05 04:52:17.739 23202-23202/com.example.qiuyu.testhellojni E/jni_thread: native_Print07-05 04:52:17.739 23202-23202/com.example.qiuyu.testhellojni D/123: 3
注:classname千万不能写错,写错之后会出现java.lang.NoClassDefFoundError错误
注:如果使用ProGuard进行混淆,很可能会找不到native方法,这个要注意
源码
Github : https://github.com/QyMars/AndroidNativeCode
总结
通过动态注册,可以避免硬编码,更加灵活,下面一章学习Native线程使用,之后要完成如何Native中启动一个线程来进行签名校验判断。
阅读全文
0 0
- Android NDK系列(6) — 动态注册native方法
- ndk注册native方法关联
- Android Studio Jni开发(三)Native方法动态注册
- Android Ndk开发入门(实现静态注册,动态注册)
- Android Studio NDK 入门教程(8)--JNI动态注册本地方法
- Android JNI动态注册Native 方法(实现IDA中改名)
- JNI搭建:native方法注册或NDK中的方法对应
- JNI搭建:native方法注册或NDK中的方法对应
- JNI搭建:native方法注册或NDK中的方法对应
- Android NDK入门(三)-- native代码的调试方法
- android NDK开发 静态/动态注册 jni
- Android JNI 动态注册方法(JNI_OnLoad)
- Android之JNI动态注册native方法和JNI数据简单使用
- Android NDK系列(2) --- 简单so例子动态分析
- 动态注册native函数
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- JDK动态代理快速入门
- java内存管理
- JDBC之最基本的CRUD操作
- java Enumset
- 一窥直播技术新趋势
- Android NDK系列(6) — 动态注册native方法
- 可变参数
- maven 之 新手入门常见问题
- TestNG+Selenium Webdriver 数据(Excel)驱动的方法
- AFN 判断网络连接类型
- [awk]练习1
- bzoj2662: [BeiJing wc2012]冻结
- C内存管理
- DAY33继承实现原理、子类调用父类的方法、封装