JNI 呼叫java裡的基本型別和物件
阿新 • • 發佈:2018-12-10
主要是介紹jni呼叫基本型別和物件,包含例項物件和靜態物件
先上mylog.h檔案
#include<android/log.h> #ifndef TEST_JNI_LOG_H #define TEST_JNI_LOG_H #define TAG "myjni-TAG" // 這個是自定義的LOG的標識 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定義LOGD型別 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定義LOGI型別 #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定義LOGW型別 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定義LOGE型別 #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定義LOGF型別 #endif //TEST_JNI_LOG_H
在上java檔案
Person.java
package com.test.myjnitest; /** * Created by Administrator on 2018/9/6 0006. */ public class Person { private int age; private String name; private static String school; public Person() { } public Person(int age, String name) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static void setSchool(String sch){ school=sch; } public static String getSchool(){ return school; } @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + '}'; } }
接著是StateListener.java
package com.test.myjnitest;
/**
* Created by Administrator on 2018/9/6 0006.
*/
public interface StateListener {
void onStateChange(int code, String msg);
void onModifyValue(Person person);
}
重要程式碼出現了
package com.test.myjnitest; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.widget.TextView; import java.util.Arrays; public class MainActivity extends AppCompatActivity { private static final String TAG = "myjniTest"; private Person xiaoming; private static String sex; private static Person xiaohua; private static final int MSG_ID = 0x100; TextView tv; private int msg_code; Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_ID: callListerner(msg_code++); if (msg_code < 10){ mHandler.sendEmptyMessageDelayed(MSG_ID,1000); } break; default: break; } } }; // Used to load the 'native-lib' library on application startup. //以下兩種方式載入lib都是可以的 static { // System.loadLibrary("native-lib"); Runtime.getRuntime().loadLibrary("native-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Example of a call to a native method tv = (TextView) findViewById(R.id.sample_text); } @Override protected void onResume() { super.onResume(); xiaoming = new Person(1, "xiaoming"); Person hello = new Person(3, "hello"); sex = "boy"; xiaohua = new Person(4, "xiaohua"); xiaohua.setSchool("beijing xiaoxue"); Log.d(TAG, "sex=" + sex + ",getSchool=" + xiaohua.getSchool() + ",xiaohua =" + xiaohua.toString() + ",xiaoming=" + xiaoming.toString()); getPersion(hello); tv.setText(xiaoming.toString() + hello.toString()); Log.d(TAG, "after getPersion sex=" + sex + ",getSchool=" + xiaohua.getSchool() + ",xiaohua =" + xiaohua.toString() + ",xiaoming=" + xiaoming.toString()); setPersionInfo(xiaoming); Log.d(TAG, "after setPersionInfo sex=" + sex + ",getSchool=" + xiaohua.getSchool() + ",xiaohua =" + xiaohua.toString() + ",xiaoming=" + xiaoming.toString()); setListener(new StateListener() { @Override public void onStateChange(int code, String msg) { Log.d(TAG, "onStateChange code=" + code + ",msg=" + msg); } @Override public void onModifyValue(Person person) { Log.d(TAG, "onModifyValue person=" + person.toString()); } }); msg_code = 0; mHandler.sendEmptyMessageDelayed(MSG_ID,1000); } @Override protected void onPause() { super.onPause(); if (mHandler.hasMessages(MSG_ID)){ mHandler.removeMessages(MSG_ID); } } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); public native void getPersion(Person person); public static native void setPersionInfo(Person persio); public native void setListener(StateListener listener); public native void callListerner(int code); }
#include <jni.h>
#include <string>
#include "mylog.h"
JavaVM *g_javaVM;
jobject g_listerner;
int mNeedDetach;
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jstring JNICALL Java_com_test_myjnitest_MainActivity_stringFromJNI(
JNIEnv *env,
jobject jthis) {
std::string hello = "Hello from C++ ";
return env->NewStringUTF(hello.c_str());
}
JNIEXPORT void JNICALL Java_com_test_myjnitest_MainActivity_getPersion(
JNIEnv *env, jobject jthis, jobject jobj) {
if (NULL == env || NULL == jthis || NULL == jobj) {
return;
}
//###################獲取MainActivity類的例項變數#########################
// 1.獲取MainActivity類Class引用
jclass jc = env->GetObjectClass(jthis);
if (NULL == jc) {
return;
}
// 2. 獲取MainActivity類例項變數xiaoming的屬性ID
jfieldID jfieldID1 = env->GetFieldID(jc, "xiaoming", "Lcom/test/myjnitest/Person;");
// 3. 獲取MainActivity類例項變數xiaoming的值
jobject jxiaoming = env->GetObjectField(jthis, jfieldID1);
// 1.獲取Person類的Class引用
jclass jPerson = env->GetObjectClass(jxiaoming);
if (NULL == jPerson) {
return;
}
// 2.獲取Person類例項變數xiaoming的age屬性ID
jfieldID jAgeID = env->GetFieldID(jPerson, "age", "I");
// 3.獲取Person類例項變數xiaoming的age的值
jint jAge = env->GetIntField(jxiaoming, jAgeID);
// 2.獲取Person類例項變數xiaoming的name屬性ID
jfieldID jNameID = env->GetFieldID(jPerson, "name", "Ljava/lang/String;");
// 3.獲取Person類例項變數xiaoming的name的值
jstring jName = (jstring) env->GetObjectField(jxiaoming, jNameID);
//轉化為可以輸出的char*
const char *cName = env->GetStringUTFChars(jName, 0);
LOGD("########## i = %d,name=%s", jAge, cName);
//釋放剛才申請的char*
env->ReleaseStringUTFChars(jName, cName);
//改變cpp裡的jage 不會影響java裡的值
jAge = 10;
//給改變java檔案的age值
env->SetIntField(jxiaoming, jAgeID, 20);
LOGD("########## i = %d", jAge);
//
jName = env->NewStringUTF("JNI_xiaoming");
env->SetObjectField(jxiaoming, jNameID, jName);
//###############獲取當前介面函式傳輸過來的形參例項變數#############################
//以下兩行都可以獲取到該類的class引用
jclass jclass1 = env->FindClass("com/test/myjnitest/Person");
// jclass jclass1 = env->GetObjectClass(jobj);
if (NULL == jclass1) {
return;
}
//通過該類的屬性獲取age的值
jfieldID jageId = env->GetFieldID(jclass1, "age", "I");
jint jage = env->GetIntField(jobj, jageId);
//通過該類的getAge獲取age的值
jmethodID jageMethodId = env->GetMethodID(jclass1, "getAge", "()I");
jint jageM = env->CallIntMethod(jobj, jageMethodId);
jmethodID jnameMethodId = env->GetMethodID(jclass1, "getName", "()Ljava/lang/String;");
jstring jnameM = (jstring) env->CallObjectMethod(jobj, jnameMethodId);
const char *cNameM = env->GetStringUTFChars(jnameM, 0);
LOGD("########## getPersion jni jage=%d,jageM=%d,cNameM=%s", jage, jageM, cNameM);
env->ReleaseStringUTFChars(jnameM, cNameM);
// jmethodID jSetAgeId = env->GetMethodID(jclass1,"setAge","(I)V");
// env->CallVoidMethod(jobj,jSetAgeId,30);
env->SetIntField(jobj, jageId, 40);
jmethodID jSetNameID = env->GetMethodID(jclass1, "setName", "(Ljava/lang/String;)V");
env->CallVoidMethod(jobj, jSetNameID, env->NewStringUTF("JNI_hello"));
//##############釋放申請的引用#############################
env->DeleteLocalRef(jclass1);
env->DeleteLocalRef(jPerson);
env->DeleteLocalRef(jc);
env->DeleteLocalRef(jxiaoming);
}
//獲取static變數或者靜態方法,使用帶有static的方法獲取即可
JNIEXPORT void JNICALL Java_com_test_myjnitest_MainActivity_setPersionInfo(
JNIEnv *env,
jclass jclass1, jobject jobj) {
if (NULL == jclass1 || NULL == env || NULL == jobj) {
return;
}
jfieldID jSexId = env->GetStaticFieldID(jclass1, "sex", "Ljava/lang/String;");
jstring jSex = (jstring) env->GetStaticObjectField(jclass1, jSexId);
const char *cSex = env->GetStringUTFChars(jSex, 0);
LOGD("########## Sex = %s", cSex);
env->ReleaseStringUTFChars(jSex, cSex);
env->SetStaticObjectField(jclass1, jSexId, env->NewStringUTF("girl"));
jfieldID jXiaohuaId = env->GetStaticFieldID(jclass1, "xiaohua", "Lcom/test/myjnitest/Person;");
jobject jXiaohua = env->GetStaticObjectField(jclass1, jXiaohuaId);
jclass jPersion = env->GetObjectClass(jXiaohua);
if (NULL == jPersion) {
return;
}
jfieldID jSchoolId = env->GetStaticFieldID(jPersion, "school", "Ljava/lang/String;");
jstring jSchool = (jstring) env->GetStaticObjectField(jPersion, jSchoolId);
const char *cSchool = env->GetStringUTFChars(jSchool, 0);
LOGD("########## cSchool = %s", cSchool);
env->ReleaseStringUTFChars(jSchool, cSchool);
env->SetStaticObjectField(jPersion, jSchoolId, env->NewStringUTF("shanghai xiaoxue"));
jfieldID jageId = env->GetFieldID(jPersion, "age", "I");
jint jage = env->GetIntField(jXiaohua, jageId);
jmethodID jNameMethodID = env->GetMethodID(jPersion, "getName", "()Ljava/lang/String;");
jstring jNameM = (jstring) env->CallObjectMethod(jXiaohua, jNameMethodID);
const char *cName = env->GetStringUTFChars(jNameM, 0);
LOGD("########## jage =%d, cName = %s", jage, cName);
env->ReleaseStringUTFChars(jNameM, cName);
env->SetIntField(jXiaohua, jageId, 8);
jmethodID jSetNameMethodId = env->GetMethodID(jPersion, "setName", "(Ljava/lang/String;)V");
env->CallVoidMethod(jXiaohua, jSetNameMethodId, env->NewStringUTF("xiaohua from JNI"));
jclass jObjClass = env->GetObjectClass(jobj);
if (NULL == jObjClass) {
return;
}
jfieldID jAgeid2 = env->GetFieldID(jObjClass, "age", "I");
jint jage2 = env->GetIntField(jobj, jAgeid2);
jmethodID jgetNameID2 = env->GetMethodID(jObjClass, "getName", "()Ljava/lang/String;");
jstring jgetName2 = (jstring) env->CallObjectMethod(jobj, jgetNameID2);
const char *cgetName2 = env->GetStringUTFChars(jgetName2, 0);
LOGD("########## jage2 =%d, cgetName2 = %s", jage2, cgetName2);
env->ReleaseStringUTFChars(jgetName2, cgetName2);
jmethodID jSetNameID2 = env->GetMethodID(jObjClass, "setName", "(Ljava/lang/String;)V");
env->CallVoidMethod(jobj, jSetNameID2,
env->NewStringUTF("JNI_xiaoming from JNI setPersionInfo"));
env->DeleteLocalRef(jXiaohua);
env->DeleteLocalRef(jPersion);
}
JNIEXPORT void JNICALL Java_com_test_myjnitest_MainActivity_setListener(
JNIEnv *env, jobject jthis, jobject jlisterner) {
if (NULL == env || NULL == jthis || NULL == jlisterner) {
return;
}
env->GetJavaVM(&g_javaVM);
if (NULL == g_javaVM) {
return;
}
g_listerner = env->NewGlobalRef(jlisterner);
}
JNIEnv *getEnvFuc() {
JNIEnv *env;
int getEnvStat = g_javaVM->GetEnv((void **) &env, JNI_VERSION_1_6);
if (getEnvStat == JNI_EDETACHED) {
if (g_javaVM->AttachCurrentThread(&env, NULL) != 0) {
return NULL;
}
mNeedDetach = JNI_TRUE;
}
return env;
}
void ReleaseEnvFuc() {
if (mNeedDetach) {
g_javaVM->DetachCurrentThread();
}
}
void listerner_onStateChange(int code) {
JNIEnv *env = getEnvFuc();
if (NULL == env) {
return;
}
jclass jclass1 = env->GetObjectClass(g_listerner);
if (NULL == jclass1) {
return;
}
jmethodID onstatechageID = env->GetMethodID(jclass1, "onStateChange", "(ILjava/lang/String;)V");
env->CallVoidMethod(g_listerner, onstatechageID, code,
env->NewStringUTF("listerner_onStateChange"));
env->DeleteLocalRef(jclass1);
jclass1 = NULL;
ReleaseEnvFuc();
env = NULL;
}
void listerner_onModifyValue(int age) {
JNIEnv *env = getEnvFuc();
if (NULL == env) {
return;
}
jclass jclass1 = env->GetObjectClass(g_listerner);
if (NULL == jclass1) {
return;
}
jmethodID onModifyValueID = env->GetMethodID(jclass1, "onModifyValue",
"(Lcom/test/myjnitest/Person;)V");
//以下是生成一個java的Person類物件
jclass jArgclass = env->FindClass("com/test/myjnitest/Person");
jmethodID initId = env->GetMethodID(jArgclass, "<init>", "(ILjava/lang/String;)V");
jobject jPerson = env->NewObject(jArgclass, initId, age,
env->NewStringUTF("listerner_onModifyValue"));
env->CallVoidMethod(g_listerner, onModifyValueID, jPerson);
env->DeleteLocalRef(jPerson);
env->DeleteLocalRef(jArgclass);
env->DeleteLocalRef(jclass1);
jclass1 = NULL;
ReleaseEnvFuc();
env = NULL;
}
JNIEXPORT void JNICALL Java_com_test_myjnitest_MainActivity_callListerner(
JNIEnv *env, jobject jthis, jint jcode) {
if (NULL == env || NULL == jthis) {
return;
}
listerner_onStateChange(jcode);
listerner_onModifyValue(jcode + 20);
}
#ifdef __cplusplus
}
#endif