1. 程式人生 > >android NDK 開發(3)

android NDK 開發(3)

1.native層呼叫java層static方法

//java層定義方法
public native static void request();
//native層執行完request後回撥此方法
public static void nativeCallBack() {
    System.out.println("nativeCallBack");
//native層實現
JNIEXPORT void JNICALL Java_com_hd_jni_JNITest_request(JNIEnv *env, jclass jclass1) {
	//調java方法
	jmethodID methodid = (*env)->GetStaticMethodID(env, jclass1, "nativeCallBack", "()V");
	(*env)->CallStaticVoidMethod(env, jclass1, methodid, NULL);
}
//測試程式碼
private void testCallback() {
    JNITest.request();
}

2.native層修改java層物件成員變數值,包括直接修改成員變數和呼叫成員方法修改 

//java層定義
public native static void modifyValue(Student student);
//native層實現
JNIEXPORT void JNICALL Java_com_hd_jni_JNITest_modifyValue
        (JNIEnv *env, jclass jclass1, jobject obj) {
    //根據傳入的物件獲得對應的class
    jclass objClass = (*env)->GetObjectClass(env, obj);
    //修改名字
    jfieldID nameid = (*env)->GetFieldID(env, objClass, "name", "Ljava/lang/String;");
    if (nameid == NULL) {
        return;
    }
    jstring nameStr = (jstring) (*env)->GetObjectField(env, obj, nameid);
    const char *name = (*env)->GetStringUTFChars(env, nameStr, NULL);

    (*env)->ReleaseStringUTFChars(env, nameStr, name);
    nameStr = (*env)->NewStringUTF(env, "name has modify");

    if (nameStr == NULL) {
        return;
    }
    (*env)->SetObjectField(env, obj, nameid, nameStr);

    //修改性別
    jmethodID sexMethodid = (*env)->GetMethodID(env, objClass, "setSex", "(I)V");
    (*env)->CallVoidMethod(env, obj, sexMethodid, 2);
}
//測試程式碼
private void testModifyValue() {
    Student student = new Student("lisi", 0);
    JNITest.modifyValue(student);
    Toast.makeText(JNITestActivity.this, "name=" + student.name + ",sex=" + student.sex, Toast.LENGTH_LONG).show();
}

 3.自定義native方法名

   1)定義方法結構體

// 結構體,分別是java層的函式名稱,簽名,對應的函式指標
	static JNINativeMethod gMethods[] = {
	        {"testChangeString", "(Ljava/lang/String;)Ljava/lang/String;", (void *) testChangeString},
	};

  2)自己實現JNI_OnLoad,寫在任何一個.c檔案都可以

JNIEXPORT jint 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;
    }
    /*
     * 如果要註冊,需要兩步,
     *    首先FindClass,
     *    然後RegisterNatives
     */
    char className[20] = {"com/hd/jni/JNITest"};

    jclass clazz = (*env)->FindClass(env, (const char *) className);
    if ((*env)->RegisterNatives(env, clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) !=
        JNI_OK) {
        printf("register native method failed!\n");
        return -1;
    }
    //一定要返回版本號,否則會出錯。
    result = JNI_VERSION_1_4;
    return result;
 }