自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件
自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件
自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件

前言

我们第一篇文章 [NDK开发]Android JNI 开发之第一个 JNI实例就是静态注册的。

除了有静态注册,还有动态注册

静态注册

静态注册:先由Java得到本地方法的声明,然后再通过JNI实现该声明方法。

  1. 优点: 理解和使用方式简单, 属于傻瓜式操作, 使用相关工具按流程操作就行, 出错率低
  2. 缺点: 当需要更改类名,包名或者方法时, 需要按照之前方法重新生成头文件, 灵活性不高

动态注册

动态注册:动态注册JAVA的Native方法,使得c/c++里面方法名 可以和 java 的Native方法名可以不同, 动态注册是将将二者方法名关联起来,以后在修改Native方法名时,只需修改动态注册关联的方法名称即可

  1. 优点: 灵活性高, 更改类名,包名或方法时, 只需对更改模块进行少量修改, 效率高
  2. 缺点: 对新手来说稍微有点难理解, 同时会由于搞错签名, 方法, 导致注册失败

正文

下面简单记录一下动态注册的使用。

系统初始化JNI在加载时,会调用JNI_OnLoad(),而卸载时会调用JNI_UnLoad();所以,我们可以通过重写JNI_OnLoad(),在JNI_OnLoad()中将函数注册到Android中,以便能通过Java访问。

第一步

MyDynamic.java代码

  1. package com.biumall.mydynamic2;
  2. public class MyDynamic {
  3. static {
  4. System.loadLibrary("MyDynamic");
  5. }
  6. /***
  7. * 1. javac MyDynamic2.java
  8. * 2. javap -s MyDynamic2.class
  9. *
  10. * public static native java.lang.String StringFormJNI();
  11. * Signature: ()Ljava/lang/String;
  12. *
  13. * public static native void StringToJNI(java.lang.String);
  14. * Signature: (Ljava/lang/String;)V
  15. *
  16. */
  17. public static native String StringFormJNI();
  18. public static native void StringToJNI(String message);
  19. }
复制

MainActivity.java

  1. public class MainActivity extends AppCompatActivity {
  2. String TAG= "Dynamic_Android_Log";
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. Log.d(TAG, "onCreate : "+ MyDynamic.StringFormJNI());
  8. MyDynamic.StringToJNI("Hello from Android.");
  9. }
  10. }
复制

第二步

MyDynamic.c

  1. #include<string.h>
  2. #include<jni.h>
  3. #include<stdio.h>
  4. #include <android/log.h>
  5. #define LOG_TAG "Dynamic_JNI_Log"
  6. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
  7. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
  8. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
  9. //获取数组大小
  10. #define ARRAY_LENGTH(x) ((int)(sizeof(x) / sizeof((x)[0])))
  11. //定义MyDynamic.java类目录(就是包名+类名,只不过.换成了/)
  12. #define DYNAMIC_CLASS "com/biumall/mydynamic2/MyDynamic"
  13. // 定义native 实现的StringFormJNI
  14. JNIEXPORT jstring JNICALL native_StringFormJNI(JNIEnv *env , jclass clasz) {
  15. LOGD("--------native_StringFormJNI----------");
  16. return (*env)->NewStringUTF(env, "Hello form JNI.");
  17. }
  18. // 定义native 实现的StringToJNI
  19. JNIEXPORT void JNICALL native_StringToJNI(JNIEnv *env, jclass clasz, jstring message){
  20. LOGD("native_StringToJNI===%s",(*env)->GetStringUTFChars(env, message, 0));
  21. }
  22. //定义JavaJNI函数的绑定表
  23. // 方法数组,分别为:
  24. // 方法名 | 方法签名 | 函数指针
  25. // 可以通过javacjavap 获取 方法签名
  26. JNINativeMethod method_table[]= {
  27. {"StringFormJNI", "()Ljava/lang/String;", (void*) native_StringFormJNI},
  28. {"StringToJNI", "(Ljava/lang/String;)V", (void *) native_StringToJNI},
  29. };
  30. int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod * methods, int methods_size){
  31. jclass clazz = NULL;
  32. //反射Java
  33. clazz = (*env)->FindClass(env, className);
  34. if(NULL == clazz){
  35. return JNI_ERR;
  36. }
  37. int result = (*env)->RegisterNatives(env, clazz, methods, methods_size);
  38. LOGD("--------registerNativeMethods---------- result : %d", result);
  39. if(result < 0){
  40. return JNI_ERR;
  41. }
  42. return JNI_OK;
  43. }
  44. JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved){
  45. JNIEnv * env = NULL;
  46. int result = (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6);
  47. LOGD("--------JNI_OnLoad----------1 result : %d", result);
  48. if(result != JNI_OK){
  49. return JNI_ERR;
  50. }
  51. result = registerNativeMethods(env , DYNAMIC_CLASS, method_table, ARRAY_LENGTH(method_table));
  52. LOGD("--------JNI_OnLoad----------2 result : %d", result);
  53. if(result != JNI_OK){
  54. return JNI_ERR;
  55. }
  56. return JNI_VERSION_1_6;
  57. }
复制

第四步

Android.mk和Application.mk,这个代码跟之前一样的。

Android.mk

  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_LDLIBS := -llog
  4. LOCAL_MODULE := MyDynamic
  5. LOCAL_SRC_FILES := MyDynamic.c
  6. include $(BUILD_SHARED_LIBRARY)
复制

Application.mk

  1. APP_ABI := all
复制

第五步

在工程中的build.gradle,新增如下内容:

  1. android {
  2. compileSdkVersion 31
  3. //
  4. sourceSets {
  5. main {
  6. jniLibs.srcDirs = ['libs']
  7. }
  8. }
  9. }
复制

参考文章

  1. Android JNI和NDK学习(03)–动态方式实现JNI
  2. [NDK开发]Android JNI 开发之第一个 JNI实例
  3. JNI静态注册和动态注册区别
  4. 你应该了解的JNI知识(一)——静态注册与动态注册
自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件

相关文章

自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件

暂无评论

none
暂无评论...