主要是介绍jni调用基本类型和对象,包含实例对象和静态对象
先上mylog.h文件
#include
#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
#include
#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, "", "(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
本文参考:https://www.jianshu.com/p/e576c7e1c403
本文源码:https://download.csdn.net/download/myjie0527/10670564