Android NDK开发(三)C语言操作Java对象

在C语言里获取Java对象的属性,执行Java对象的方法和反射很像。

方法说明

1、获取jclass

jclass      (*FindClass)(JNIEnv*, const char*);

其中第二个参数是类名。

2、获取方法ID

方法ID可以代表一个方法,就像c语言里函数指针一样

    jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);

第三个参数是方法名,构造函数的方法名是这里写图片描述
第四个参数是方法签名,如何获取方法签名,可以通过javap。
首先编译生成class文件,切换到${project_dir}/bin/classes/下,执行命令
Android NDK开发(三)C语言操作Java对象_第1张图片
这就是签名

3、执行构造方法

jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
jobject NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args);
jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);

Constructs a new Java object. The method ID indicates which constructor method to invoke. This ID must be obtained by calling GetMethodID() with as the method name and void (V) as the return type.
The clazz argument must not refer to an array class.

4、执行普通方法

  void (*CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);

这是一个系列方法,方法名和参数可以参考jni.h或者这里写链接内容

sample

1、新建项目,添加一个类

package net.qingtian.object;

public class Coder {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

2、创建native方法

public class MainActivity extends Activity {
    public native Coder generateCoder(String name, int age);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

3、在命令行,cd 到src目录下,执行命令

这里写图片描述

4、在项目跟目录下创建jni文件夹,把第3步生成的net_qingtian_object_MainActivity.h头文件拷贝在该目录下

5、 在jni目录下新建一个c代码源文件,叫object.c,在object.c里把net_qingtian_object_MainActivity.h头文件里的方法给实现了

#include "net_qingtian_object_MainActivity.h"

JNIEXPORT jobject JNICALL Java_net_qingtian_object_MainActivity_generateCoder
  (JNIEnv * env, jobject obj, jstring name, jint age){

    // 获取class
    jclass clazz = (*env)->FindClass(env, "net/qingtian/object/Coder");

    // 获取构造方法id
    jmethodID constructionMethodId = (*env)->GetMethodID(env, clazz, "<init>", "()V");

    // 创建对象
    jobject returnObj = (*env)->NewObject(env, clazz, constructionMethodId);

    // 给对象设置name属性
    jmethodID setNameMethodId = (*env)->GetMethodID(env, clazz, "setName", "(Ljava/lang/String;)V");
    (*env)->CallNonvirtualVoidMethod(env, returnObj, clazz, setNameMethodId, name);

    // 给对象设置age属性
    jmethodID setAgeMethodId = (*env)->GetMethodID(env, clazz, "setAge", "(I)V");
    (*env)->CallNonvirtualVoidMethod(env, returnObj, clazz, setAgeMethodId, age);

    return returnObj;

}

6、 在jni下编写Android.mk,这是和编译打包有关系的脚本文件

   LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)
   # 对应打包成函数库的名字
   LOCAL_MODULE    := object
   # 对应c代码的文件
   LOCAL_SRC_FILES := object.c

   include $(BUILD_SHARED_LIBRARY)

7、编译共享库

在linux环境下切换到项目根目录(cygwin),执行ndk-build命令。
这里写图片描述

8、在java方法里添加调用native方法的代码

public class MainActivity extends Activity {
    static {
        System.loadLibrary("object");
    }
    public native Coder generateCoder(String name, int age);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Coder coder = generateCoder("张三", 24);
        Log.e("qingtian", "name:"+coder.getName());
        Log.e("qingtian", "age:"+coder.getAge());
    }
}

9、运行项目

Android NDK开发(三)C语言操作Java对象_第2张图片

你可能感兴趣的:(android,jni,C语言,NDK)