JNI方法的静态注册和动态注册RegisterNatives
2017-11-25 10:37
447 查看
代码结构如下:
Android下的Java代码 仍然还是使用了eclipse开发环境 这里在NDKUtils.java文件里定义了所有的本地方法
Linux下的C代码 这里是在Linux系统目录下新建的文件 其中libs/和obj/都是由ndk-build编译后编译器产生
点击查看完整项目代码JniDemo-master
这次的编译没有使用windows下的工具Cygwin64
而是直接在Linux系统下使用ndk-build工具生成对应的动态库(/libs/armeabi/libzzyJni.so)
直接使用ndk-build脚本编译出动态库也是非常简单的 在Linux宿主机上不需要安装和配置
只需要把android-ndk-r14b-linux-x86_64.zip解压到机器上 通过export导入路径到系统配置下就能直接使用
操作方法:
1 下载Linux版本的android-ndk-r14b-linux-x86_64.zip (我的Linux设备为Ubuntu64位操作系统)
2 导入ndk目录到系统配置,这里我使用了仅为我当前登录的用户有效
3 到/JniDemo-master/jni/目录下直接执行ndk-build脚本生成libs/和obj/目录以及动态库
4 拷贝动态库libzzyJni.so到eclipse对应的/libs/armeabi/libzzyJni.so
5 编译安卓应用程序到手机
NDK脚本的导入方法:
android-ndk-r14b-linux-x86_64/目录下执行两条export导入命令
或者写成脚本
执行脚本 source export_ndk.sh
这里不是执行 sh export_ndk.sh
当在一个终端shell中执行一个sh脚本,本质是创建一个子进程来执行sh脚本中的命令,当执行export时,变量加入子进程的环境变量(而非父进程shell). 当脚本执行结束,子进程销毁. 返回父进程,父进程的环境变量没有任何变化
若希望嵌入linux启动时加入的环境变量, 可以直接将export的环境变量添加到/etc/profile
若希望在ubuntu上为特定用户添加环境变量,可以在~/.bashrc文件中添加
在/JniDemo-master目录下执行ndk-build脚本生成obj/和libs/libzzyJni.so动态库
还在使用古老的eclipse 是因为已经有一段时间没有做安卓项目 所以没有使用Android studio
如果使用AS开发的话 就不需要手动编写 Android.mk 等编译的脚本文件
这里关于编译脚本中指定使用哪种架构的CPU还做了区分armeabi或者armeabi-v7a 或者其他类型
在Application.mk中可以看到我已经指定编译的CPU类型为 armeabi
就做个简单介绍
Android 设备的CPU类型(通常称为”ABIs”)
armeabiv-v7a: 第7代及以上的 ARM 处理器。2011年15月以后的生产的大部分Android设备都使用它.
arm64-v8a: 第8代、64位ARM处理器,很少设备,三星 Galaxy S6是其中之一。
armeabi: 第5代、第6代的ARM处理器,早期的手机用的比较多。
x86: 平板、模拟器用得比较多。
x86_64: 64位的平板。
最后关于查看库中存在哪些函数方法:
使用nm命令失败的话 nm: no symbols
可以使用
运行在JM虚拟机上的Java代码是怎么样找到对应的本地方法的
这里有两种方法可以找到
1 C/C++代码的函数名以包名加上函数声明的形式让Java代码找到 属于静态方式
2 C/C++通过JNIEnv中的RegisterNatives方法注册函数名 属于动态方式
动态注册方式:
JNI_OnLoad函数作为JNI加载的入口,直接在这里进行函数的动态注册
点击查看完整项目代码JniDemo-master
Android下的Java代码 仍然还是使用了eclipse开发环境 这里在NDKUtils.java文件里定义了所有的本地方法
Linux下的C代码 这里是在Linux系统目录下新建的文件 其中libs/和obj/都是由ndk-build编译后编译器产生
点击查看完整项目代码JniDemo-master
// MainActivity.java public class MainActivity extends Activity implements View.OnClickListener { private Button btnJni1, btnJni2, btnJni3; private TextView tvShowInfo; private NDKUtils jniUtil; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { jniUtil = new NDKUtils(); btnJni1 = (Button) findViewById(R.id.btnJni1); btnJni1.setOnClickListener(this); btnJni2 = (Button) findViewById(R.id.btnJni2); btnJni2.setOnClickListener(this); btnJni3 = (Button) findViewById(R.id.btnJni3); btnJni3.setOnClickListener(this); tvShowInfo = (TextView) findViewById(R.id.tvShowInfo); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.btnJni1: tvShowInfo.setText(String.format("【静态调用Jni】获取String,输出为:\n %s", jniUtil.getVipString())); break; case R.id.btnJni2: tvShowInfo.setText(String.format("【静态调用Jni】输入vip,加密输出为:\n %s", jniUtil.staticGenerateKey("vip"))); break; case R.id.btnJni3: tvShowInfo.setText(String.format("【动态调用Jni】输入test,加密输出为:\n %s", jniUtil.dynamicGenerateKey("test"))); break; default: break; } } }
// NDKUtils.java public class NDKUtils { static { System.loadLibrary("zzyJni"); } public native String getVipString(); public native String staticGenerateKey(String name); public native String dynamicGenerateKey(String name); }
这次的编译没有使用windows下的工具Cygwin64
而是直接在Linux系统下使用ndk-build工具生成对应的动态库(/libs/armeabi/libzzyJni.so)
直接使用ndk-build脚本编译出动态库也是非常简单的 在Linux宿主机上不需要安装和配置
只需要把android-ndk-r14b-linux-x86_64.zip解压到机器上 通过export导入路径到系统配置下就能直接使用
操作方法:
1 下载Linux版本的android-ndk-r14b-linux-x86_64.zip (我的Linux设备为Ubuntu64位操作系统)
2 导入ndk目录到系统配置,这里我使用了仅为我当前登录的用户有效
3 到/JniDemo-master/jni/目录下直接执行ndk-build脚本生成libs/和obj/目录以及动态库
4 拷贝动态库libzzyJni.so到eclipse对应的/libs/armeabi/libzzyJni.so
5 编译安卓应用程序到手机
NDK脚本的导入方法:
android-ndk-r14b-linux-x86_64/目录下执行两条export导入命令
/android-ndk-r14b$ export ANDROID_NDK=/home/admin/tools/android-ndk-r14b /android-ndk-r14b$ export PATH=$PATH:$ANDROID_NDK
或者写成脚本
#Android NDK export_ndk.sh export ANDROID_NDK=/home/admin/tools/android-ndk-r14b export PATH=$PATH:$ANDROID_NDK
执行脚本 source export_ndk.sh
这里不是执行 sh export_ndk.sh
当在一个终端shell中执行一个sh脚本,本质是创建一个子进程来执行sh脚本中的命令,当执行export时,变量加入子进程的环境变量(而非父进程shell). 当脚本执行结束,子进程销毁. 返回父进程,父进程的环境变量没有任何变化
若希望嵌入linux启动时加入的环境变量, 可以直接将export的环境变量添加到/etc/profile
若希望在ubuntu上为特定用户添加环境变量,可以在~/.bashrc文件中添加
在/JniDemo-master目录下执行ndk-build脚本生成obj/和libs/libzzyJni.so动态库
/JniDemo-master$ ndk-build
还在使用古老的eclipse 是因为已经有一段时间没有做安卓项目 所以没有使用Android studio
如果使用AS开发的话 就不需要手动编写 Android.mk 等编译的脚本文件
这里关于编译脚本中指定使用哪种架构的CPU还做了区分armeabi或者armeabi-v7a 或者其他类型
在Application.mk中可以看到我已经指定编译的CPU类型为 armeabi
APP_PLATFORM = android-23 APP_ABI := armeabi APP_STL := stlport_static APP_OPTIM := debug
就做个简单介绍
Android 设备的CPU类型(通常称为”ABIs”)
armeabiv-v7a: 第7代及以上的 ARM 处理器。2011年15月以后的生产的大部分Android设备都使用它.
arm64-v8a: 第8代、64位ARM处理器,很少设备,三星 Galaxy S6是其中之一。
armeabi: 第5代、第6代的ARM处理器,早期的手机用的比较多。
x86: 平板、模拟器用得比较多。
x86_64: 64位的平板。
最后关于查看库中存在哪些函数方法:
使用nm命令失败的话 nm: no symbols
可以使用
$ objdump -tT libzzyJni.so
运行在JM虚拟机上的Java代码是怎么样找到对应的本地方法的
这里有两种方法可以找到
1 C/C++代码的函数名以包名加上函数声明的形式让Java代码找到 属于静态方式
2 C/C++通过JNIEnv中的RegisterNatives方法注册函数名 属于动态方式
动态注册方式:
#include <jni.h> static JNINativeMethod methods[] = { {"dynamicGenerateKey", "(Ljava/lang/String;)Ljava/lang/String;", (void *) native_dynamic_key}, }; 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; } static int registerNatives(JNIEnv *env) { const char *className = "demo/jnidemo/NDKUtils"; //指定注册的类 return registerNativeMethods(env, className, methods, sizeof(methods) / sizeof(methods[0])); } 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) { return -1; } assert(env != NULL); if (!registerNatives(env)){ return -1; } return JNI_VERSION_1_4; }
JNI_OnLoad函数作为JNI加载的入口,直接在这里进行函数的动态注册
点击查看完整项目代码JniDemo-master
相关文章推荐
- Android JNI动态注册Native 方法(实现IDA中改名)
- Android JNI使用方法(“动态注册”)
- JNI-使用RegisterNatives注册本地方法
- JNI动态注册方法
- Android Studio NDK 入门教程(8)--JNI动态注册本地方法
- Android JNI静态和动态注册 、Java Reflect(C或C++层反射和JAVA层反射)、Java 可变参数(JNI实现)
- Android之JNI动态注册native方法和JNI数据简单使用
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- 静态注册JNI和动态注册JNI
- AndroidJNI实践(1)-使用.h头文件-静态注册JNI方法
- JNI原理与静态、动态注册
- 静态注册JNI和动态注册JNI
- Android深入理解JNI(一)JNI原理与静态、动态注册
- Android深入理解JNI(一)JNI原理与静态、动态注册
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- Android JNI使用方法(“动态注册”)
- android开发--- jni使用RegisterNatives注册本地方法
- JNI动态注册native方法及JNI数据使用
- 安卓 jni 开发之 native 方法的动态注册
- JNI动态注册native方法及JNI数据使用