美文网首页Android基础知识
NDK开发(三) :JNI访问Java变量和方法

NDK开发(三) :JNI访问Java变量和方法

作者: 103style | 来源:发表于2019-08-19 15:46 被阅读0次

    转载请以链接形式标明出处:
    本文出自:103style的博客

    本文操作以 Android Studio 3.4.2 版本为例


    NDK开发文章汇总

    前先阅读 JNI的数据类型


    目录

    • JNI访问Java成员变量
    • JNI访问Java静态变量
    • JNI访问Java非静态方法
    • JNI访问Java静态方法
    • JNI访问Java构造方法
    • 小结
    • 参考文章

    JNI访问Java成员变量

    我们在 Demo HelloNDK 这里继续添加示例。

    • 首先定义变量showText

      public String showText = "Hello World";
      
    • 添加native方法accessField()

      public native void accessField();
      

      选中accessField,按 Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessField

    • 在方法中实现修改属性的逻辑:

      extern "C"
      JNIEXPORT void JNICALL
      Java_com_example_myapplication_MainActivity_accessField(JNIEnv *env, jobject instance) {
          //获取类
          jclass jcla = env->GetObjectClass(instance);
          //获取类的成员变量showText的id
          jfieldID jfId = env->GetFieldID(jcla, "showText", "Ljava/lang/String;");
      
          jstring after = env->NewStringUTF("Hello NDK");
          //修改属性id对应的值
          env->SetObjectField(instance, jfId, after);
      }
      
    • 调用验证结果:

      TextView accessFiledShow = findViewById(R.id.tv_access_filed_show);
      String res = "before: " + showText;
      //通过ndk 修改成员变量
      accessField();
      res += ", after:" + showText;
      accessFiledShow.setText(res);
      

    JNI访问Java静态变量

    我们在 Demo HelloNDK 这里继续添加示例。

    • 同上添加静态属性和 native方法:
      private static String staticString = "static string";
      
      public native void accessStaticField();
      
    • Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessStaticField,添加如下代码:
      extern "C"
      JNIEXPORT void JNICALL
      Java_com_example_myapplication_MainActivity_accessStaticField(JNIEnv *env, jobject instance) {
          //获取类
          jclass oClass = env->GetObjectClass(instance);
          //获取静态变量id
          jfieldID staticFid = env->GetStaticFieldID(oClass, "staticString", "Ljava/lang/String;");
      
          //设置静态变量
          jstring after = env->NewStringUTF("static field update in jni");
          env->SetStaticObjectField(oClass, staticFid, after);
      }
      
    • 调用验证结果:
      TextView accessStaticFiledShow = findViewById(R.id.tv_static_access_filed_show);
      res = "before: " + staticString;
      //通过ndk 修改静态变量
      accessStaticField();
      res += ", after:" + staticString;
      accessStaticFiledShow.setText(res);
      

    JNI访问Java非静态方法

    我们在 Demo HelloNDK 这里继续添加示例。

    • 同上添加Java非静态方法和 native方法:
      public native String accessMethod();
      
      public String getAuthName(String name) {
          Log.e(TAG, "name = " + name);
          return name;
      }
      
    • Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessMethod,添加如下代码:
      extern "C"
      JNIEXPORT jstring JNICALL
      Java_com_example_myapplication_MainActivity_accessMethod(JNIEnv *env, jobject instance) {
          //获取类
          jclass jCla = env->GetObjectClass(instance);
          //获取方法id  第二个参数:方法名  第三个参数:(参数)返回值 的类型描述
          jmethodID methodID = env->GetMethodID(jCla, "getAuthName",
                                                "(Ljava/lang/String;)Ljava/lang/String;");
          jstring res = env->NewStringUTF("103style");
          jobject objRes = env->CallObjectMethod(instance, methodID, res);
          return static_cast<jstring>(objRes);
      }
      
    • 调用验证结果:
      TextView tvName = findViewById(R.id.tv_auth_name);
      res = "authName = " + accessMethod();
      tvName.setText(res);
      

    JNI访问Java静态方法

    我们在 Demo HelloNDK 这里继续添加示例。

    • 同上添加Java静态方法和 native方法:

      private static int getRandomValue(int max) {
          return new Random().nextInt(max);
      }
      
      public native int accessStaticMethod(int max);
      
    • Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessStaticMethod__I,添加如下代码:

      extern "C"
      JNIEXPORT jint JNICALL
      Java_com_example_myapplication_MainActivity_accessStaticMethod__I(JNIEnv *env, jobject instance,
                                                                        jint max) {
          //获取类
          jclass jCla = env->GetObjectClass(instance);
          //获取静态方法的id
          jmethodID methodID = env->GetStaticMethodID(jCla, "getRandomValue", "(I)I");
          //调用静态方法
          jint res = env->CallStaticIntMethod(jCla, methodID, max);
          //返回结果
          return res;
      }
      
    • 调用验证结果:

      TextView staticMethodShow = findViewById(R.id.tv_static_method_show);
      res = "accessStaticMethod(100) = " + accessStaticMethod(100);
      staticMethodShow.setText(res);
      

    JNI访问Java构造方法

    我们在 Demo HelloNDK 这里继续添加示例。

    • 同上添加 native方法:

      public native Date accessConstructor();
      
    • Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessConstructor,添加如下代码:

      extern "C"
      JNIEXPORT jobject JNICALL
      Java_com_example_myapplication_MainActivity_accessConstructor(JNIEnv *env, jobject instance) {
          //得到TestClass对应的jclass
      //    jclass jCla = env->FindClass("com/example/myapplication/TestClass");
          jclass jCla = env->FindClass("java/util/Date");
          //获取构造函数的methodId  构造函数为 void函数 对应的方法名为<init>
          jmethodID methodID = env->GetMethodID(jCla, "<init>", "()V");
          jobject jTestClass = env->NewObject(jCla, methodID);
          return jTestClass;
      }
      
    • 调用验证结果:

      TextView staticConstShow = findViewById(R.id.tv_const_show);
      res = accessConstructor().toString();
      staticConstShow.setText(res);
      

    小结

    • JNI获取类的成员变量的ID调用GetFieldID获取,通过Set[类型]Field修改变量值。
    • JNI获取类的成员变量的ID调用GetStaticFieldID获取,通过SetStatic[类型]Field修改变量值。
    • JNI获取类的方法的ID调用GetMethodID获取,通过Call[类型]Method调用方法。
    • JNI获取类的静态方法的ID调用GetStaticMethodID获取,通过CallStatic[类型]Method调用方法。
    • JNI获取类的构造方法的ID调用GetMethodID获取,通过NewObject构造,构造函数名为"<init>"
    • Demo地址

    参考文章


    以上

    相关文章

      网友评论

        本文标题:NDK开发(三) :JNI访问Java变量和方法

        本文链接:https://www.haomeiwen.com/subject/tzzjsctx.html