前言
之前其实写过,代码不见了,为了走一下流程,重新简单的写了一个。
正文
动态注册
动态注册java的Native方法,使得c/c++方法名可以和java的Native方法名可以不同。动态注册是将二者方法名关联起来,以后在修改Native方法名时,只需修改动态注册关联的方法名称即可。
-
优点: 灵活性高, 更改类名,包名或方法时, 只需对更改模块进行少量修改, 效率高
-
缺点: 对新手来说稍微有点难理解, 同时会由于搞错签名, 方法, 导致注册失败
实战
定义Hello.java
package com.biumall.dynamic.one; public class Hello { // 1. load Hello.so static { System.loadLibrary("Hello"); } // 2. define native hello() public static native String hello(); }
动态注册需要Java中native的Method(本地方法名)和Signature(签名)
对于Method(本地方法名),很简单就是上面hello。
当对于Signature(签名),需要通过一定的方式获取。
两种方式多需要先javac
#当前位置:BiuJniDynamic\src\main\java\com\biumall\dynamic\one javac Hello.java
获取签名方式一
在javac基础上进行javap -s
#当前位置:BiuJniDynamic\src\main\java\com\biumall\dynamic\one javap -s hello.class
命令行就会显示hello()方法的签名。
public static native java.lang.String hello(); Signature: ()Ljava/lang/String;
获取签名方式二
方式跟静态注册一样,javac后,退回java所在目录,进行javah
#当前位置:BiuJniDynamic\src\main\java javah com.biumall.dynamic.one.Hello
得到
com_biumall_dynamic_one_Hello.h
.h里面的方法上会有Method和Signature注释
/* * Class: com_biumall_dynamic_one_Hello * Method: hello * Signature: ()Ljava/lang/String; */
Hello.c
动态注册跟静态不一
系统初始化JNI在加载时,会调用JNI_OnLoad(),而卸载时会调用JNI_UnLoad();所以,我们可以通过重写JNI_OnLoad(),在JNI_OnLoad()中将函数注册到Android中,以便能通过Java访问。
下面是完整代码
#include <jni.h> #include <android/log.h> #include<stdio.h> //LOG_TAG #define LOG_TAG "from_dynamic_jni_" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) //获取数组大小 #define ARRAY_LENGTH(x) ((int)(sizeof(x) / sizeof((x)[0]))) //定义Hello.java类路径[包名+类名,只不过.换成了/] //com.biumall.dynamic.one.Hello #define DYNAMIC_CLASS "com/biumall/dynamic/one/Hello" //native 方法 JNIEXPORT jstring JNICALL native_hello (JNIEnv * env , jclass jclazz){ LOGE("native_hello()"); return (*env)->NewStringUTF(env, "Hello World !!!! --- from JNI "); }; //定义Java和JNI函数的绑定表 // 方法数组,分别为:(方法名[java层定义的],方法签名,函数指针[c层对应替换的方法]) // 可以通过javac和javap 获取 方法签名 JNINativeMethod method_table[]= { {"hello", "()Ljava/lang/String;", (void*) native_hello}, }; int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod * methods, int methods_size){ jclass clazz = NULL; //反射Java类 clazz = (*env)->FindClass(env, className); if(NULL == clazz){ return JNI_ERR; } int result = (*env)->RegisterNatives(env, clazz, methods, methods_size); LOGD("--------registerNativeMethods---------- result : %d", result); if(result < 0){ return JNI_ERR; } return JNI_OK; } JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved){ JNIEnv * env = NULL; int result = (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6); LOGD("--------JNI_OnLoad----------1 result : %d", result); if(result != JNI_OK){ return JNI_ERR; } result = registerNativeMethods(env , DYNAMIC_CLASS, method_table, ARRAY_LENGTH(method_table)); LOGD("--------JNI_OnLoad----------2 result : %d", result); if(result != JNI_OK){ return JNI_ERR; } return JNI_VERSION_1_6; }
上面大部分有注释,这里就不重复了。
至于其他的Application.mk,Android.mk,ndk-build和build.gradle配置跟静态注册一样,这里就懒得重复了。
可以看最近整理的《》
参考文章
-
《》
-
《》
-
《》
-
《》
历史上的今天
暂无评论...
随机推荐
Internet时间同步服务器地址
阿里云提供了7个NTP时间服务器也就是Internet时间同步服务器地址ntp1.aliyun.comntp2.aliyun.comntp3.aliyun.comntp4.aliyun.comntp5.aliyun.comntp6.aliyun.comntp7.aliyun.c...
《MySQL基础教程》笔记8
前言主要是介绍PHP脚本操作MySQL。根据《MySQL基础教程-西泽梦路》学习,简单的做一下笔记。记录于此,方便自己回忆。正文PDO什么是PDOPDO是PHP 5.1.0及更高版本中定义的标准数据库连接机制,其目的是更方便地利用数据库。PDO是用于管理数据库的“类”(class),...
code 4874 SQLITE_IOERR_SHMSIZE
前言最近使用SQLite,出现一些问题,因此整理于此,也摘抄了网上的其他问题。好记性不如烂笔头正文code 4874disk I/O error (code 4874 SQLITE_IOERR_SHMSIZE)最近使用SQLite,出现如下异常。SQLiteLog: (4874) d...
梁实秋:快乐
天下最快乐的事大概莫过于做皇帝。“首出庶物,万国咸宁”。至不济可以生杀予夺,为所欲为。至于后宫粉黛三千,御膳八珍罗列,更是不在话下。清乾隆皇帝,“称八旬之觞,镌十全之宝”,三下江南,附庸风雅。那副志得意满的神情,真是不能不令人兴起“大丈夫当如是也”的感喟。在穷措大眼里,九五之尊,乐不可支。但是试起...
使用adb shell命令启动动画
adb shell 命令Adb的全称为Android Debug Bridge:android调试桥梁。Android的初衷是用adb这样的一个工具来协助开发人员在开发android应用的过程中更快更好的调试apk,因此adb具有安装卸载apk、拷贝推送文件、查看设备硬件信息、查看应用程序占用...
OkHttp分析之异步请求
前言前面两篇文章介绍了OKHttp的《OkHttp简单介绍之一》和《OkHttp分析之同步请求》,大概的流程都介绍了,但上一篇只介绍了同步的,因此异步的也单独介绍一下,因为这个部分线程管理的思路很不错。正文OKHttp同步请求和异步请求唯一区别点是异步请求用了线程池管理,其的都是一样的,因此...