Android JNI之C/C++層調用JAVA


從C/C++層調用JAVA層代碼步驟:

1. 在JAVA類中創建java方法和本地方法

public class TestNdk{
int a;//本示例中將被修改的JAVA變量 Handler handler;
public TestNdk(Handler handler){ this.handler = handler; setUp(); } public native void setUp();//本地方法 public native static int getStringFromNative();//本地方法 public int getA() { return a; } public native void setA(int a);//本地方法 public void notifyFiledChange(){//本示例中將被C/C++調用的JAVA方法 Message message = new Message(); Bundle bundle = new Bundle(); bundle.putInt("a",a); message.setData(bundle); message.what=1; handler.sendMessage(message); } static { System.loadLibrary("MyJni");//導入生成的鏈接庫文件 } }

2.在JNI文件夾下創建類對應的.h文件(可通過JAVAH命令生成該類的.h文件,就不贅述了),創建.cpp文件(用於編寫C/C++層的代碼)

.h文件:

#ifndef _Included_com_x_mp4player_TestNdk
#define _Included_com_x_mp4player_TestNdk
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_x_mp4player_TestNdk
 * Method:    setUp
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setUp
  (JNIEnv *, jobject);

/*
 * Class:     com_x_mp4player_TestNdk
 * Method:    setA
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setA
        (JNIEnv *env, jobject thiz,jint i);

/*
 * Class:     com_x_mp4player_TestNdk
 * Method:    getStringFromNative
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_x_mp4player_TestNdk_getStringFromNative
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

.cpp文件

#include <jni.h>
#include <com_x_mp4player_TestNdk.h>

jobject m_object;
jmethodID m_mid;
jfieldID m_fid;

JNIEXPORT jint JNICALL Java_com_x_mp4player_TestNdk_getStringFromNative
        (JNIEnv *env, jclass cls) {
    return 1;
}

JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setUp
        (JNIEnv *env, jobject thiz) {
    jclass clazz = (*env).GetObjectClass(thiz);//獲取該對象的類
    m_object = (*env).NewGlobalRef(thiz);//創建對象的本地變量
    m_mid =(*env).GetMethodID(clazz, "notifyFiledChange", "()V");//獲取JAVA方法的ID
    m_fid = (*env).GetFieldID(clazz,"a","I");//獲取java變量的ID
    return;
}

JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setA
        (JNIEnv *env, jobject thiz,jint i) {
    (*env).SetIntField( m_object, m_fid,i);
    (*env).CallVoidMethod(m_object,m_mid);
    return;
}

3.調用JAVA方法需要類的對象

在C/C++層獲取類的對象的方法有兩種:

  • 通過JAVA層調用本地方法(如示例中的setUp()方法),在調用時,會傳入對象jobject或者對象的類jclass

JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setUp
        (JNIEnv *env, jobject thiz) {
    ...
    jclass clazz = (*env).GetObjectClass(thiz);//獲取該對象的類
    ...
    return;
}
  • 通過C/C++創建java對象

方法如下:

1.通過JAVA層的本地方法創建同類對象

步驟:

I.通過對象獲取類

II.通過類獲取類的構造方法的ID

III.基於方法ID和類,創建新對象

JNIEXPORT void JNICALL JAVA_nativeMethod
        (JNIEnv *env, jobject thiz,jint i){
    ...
    jclass clazz = (*env).GetObjectClass(thiz);
    jmethodID mid = (*env).GetMethodID(clazz,"<init>","()V");
    jobject obj = (*env).NewObject(clazz,mid);
    ...
    return;
}

2.通過C/C++創建不同類對象

步驟:

I.通過FindClass方法獲取需要的類

II.通過類獲取類的構造方法的ID

III.基於方法ID和類,創建新對象

JNIEXPORT void JNICALL JAVA_nativeMethod
        (JNIEnv *env, jobject thiz,jint i){
    ...
    jclass clazz = (*env).FindClass("com/x/test/Test");//參數為類路徑
    jmethodID mid = (*env).GetMethodID(clazz,"<init>","()V");
    jobject obj = (*env).NewObject(clazz,mid);
    ...
    return;
}

3.通過C++直接創建

4.調用java方法的步驟:

  1. 獲取類的方法ID
  2. 基於對象和方法id調用JAVA方法

  • 示例中是java調用本地方法setUp后,調用本地方法setA(int i),在本地方法setA(int i)中調用JAVA方法notifyFiledChange()方法

5.C/C++直接存取JAVA變量

  1. 獲取對象的變量的ID
  2. 基於對象和變量id存取變量

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM