天天看點

android NDK 之C調java屬性及方法

最近有時間,研究了下android NDK 的使用方法,記錄下,與大家一起分享;

android NDK環境配置就不介紹啦,網上太多。

下圖是執行代碼 後顯示結果:

android NDK 之C調java屬性及方法
android NDK 之C調java屬性及方法

直接上代碼,代碼句句有描述;

MainActivity.java

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("native-lib");
    }

    private String name;
    private static int age = 10;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        changeName();
        changeAge();
        String uuid = uuid();
        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(stringFromJNI() + "\n name:" + name + "\n age:" + age + "\n uuid: " + uuid + "\n uuid2:" + staticUUID());
    }

    public String getUUID() {
        return UUID.randomUUID().toString();
    }

    private static String getStaticUUID() {
        return UUID.randomUUID().toString();
    }

    public native String stringFromJNI();

    public native void changeName();

    public native void changeAge();

    public native String uuid();

    private native String staticUUID();


}
           

如下是c檔案的内容:

native-lib.cpp

#include <jni.h>
#include <string>
#include <android/log.h>


//傳回一個jstring
extern "C"
JNIEXPORT jstring JNICALL
Java_com_bxn_ndkdemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    char hello[] = "Hello from C++";
    return env->NewStringUTF(hello);
}

//改變java 非靜态屬性 name
extern "C"
JNIEXPORT void JNICALL
Java_com_bxn_ndkdemo_MainActivity_changeName(
        JNIEnv *env,
        jobject jobj) {

    //通過jobj得到 jclass(MainActivity.class)
    jclass clas = env->GetObjectClass(jobj);

    //得到屬性id
    jfieldID fielId = env->GetFieldID(clas, "name", "Ljava/lang/String;");

    //建立一個c中的字元串
    char str[] = "hello ch";

    //把c中的字元串,轉成jni字元串
    jstring jstr = env->NewStringUTF(str);

    //設定 java中的屬性
    env->SetObjectField(jobj, fielId, jstr);
}

//改變java靜态屬性
extern "C"
JNIEXPORT void JNICALL
Java_com_bxn_ndkdemo_MainActivity_changeAge(
        JNIEnv *env,
        jobject jobj) {

    //通過jobj得到 jclass(MainActivity.class)
    jclass clas = env->GetObjectClass(jobj);

    //得到靜态屬性id
    jfieldID fielId = env->GetStaticFieldID(clas, "age", "I");

    //得到靜态屬性的值
    jint jint1 = env->GetStaticIntField(clas, fielId);
    //自加1
    jint1 += 1;
    //設定 java靜态屬性
    env->SetStaticIntField(clas, fielId, jint1);
}


//調用java非靜态方法
extern "C"
JNIEXPORT jstring JNICALL
Java_com_bxn_ndkdemo_MainActivity_uuid(
        JNIEnv *env,
        jobject jobj) {

    //通過jobj得到 jclass(MainActivity.class)
    jclass clas = env->GetObjectClass(jobj);
    //得到靜态方法的id
    jmethodID jmID = env->GetMethodID(clas, "getUUID", "()Ljava/lang/String;");

    //調用java中的非靜态方法
    jstring jstr = (jstring) env->CallObjectMethod(jobj, jmID);

    //将jni中的字元轉成c中的字元
    const char *uuid_str = env->GetStringUTFChars(jstr, NULL);

    //這條指令是在LOGCAT中列印(可忽略)
    __android_log_print(ANDROID_LOG_INFO, "JNITag", "%s", uuid_str);

    return jstr;

}


//調用java靜态方法
extern "C"
JNIEXPORT jstring JNICALL
Java_com_bxn_ndkdemo_MainActivity_staticUUID(
        JNIEnv *env,
        jobject jobj) {

    //通過jobj得到 jclass(MainActivity.class)
    jclass clas = env->GetObjectClass(jobj);
    //得到java中的靜态方法id
    jmethodID jmID = env->GetStaticMethodID(clas, "getStaticUUID", "()Ljava/lang/String;");
    //調用java中靜态方法
    jstring jstr = (jstring) env->CallStaticObjectMethod(clas, jmID);
    //将jni中的字元轉成c中的字元
    const char *uuid_str = env->GetStringUTFChars(jstr, NULL);
    //這條指令是在LOGCAT中列印(可忽略)
    __android_log_print(ANDROID_LOG_INFO, "JNITag", "%s", uuid_str);

    return jstr;
}



           

------------------------------------------------------------------------------------

裡面有涉及到 java中 屬性及方法的簽名 如  String : ”Ljava/lang/String"    

可通過 javap -s -p XXX  (XXX為類名)

得到,如果本文介紹的為MainActivity類,

android NDK 之C調java屬性及方法
android NDK 之C調java屬性及方法