JNI调用Java方法
Posted 胡刚2021
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JNI调用Java方法相关的知识,希望对你有一定的参考价值。
推荐阅读:JNI/NDK入门指南之JNI多线程回调Java方法
1.JNI 调用 Java 无参数无返回值的方法
public native void native_call_java_callBack_method();
public void callBack()
Toast.makeText(this, "调用java无参无返回值方法", Toast.LENGTH_LONG).show();
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myjnicalljava_MainActivity_native_1call_1java_1callBack_1method(JNIEnv *env,
jobject thiz)
// TODO: implement native_call_java_callBack_method()
LOGI("=========== native_call_java_callBack_method ===========");
jclass jcl = env->GetObjectClass(thiz);
jmethodID mid = env->GetMethodID(jcl, "callBack", "()V");
env->CallVoidMethod(thiz, mid);
2.JNI 调用 Java 整型参数无返回值方法
public native void native_call_java_integer_signature_callBack_method();
public void callBack(int num)
Toast.makeText(this, "调用java有参无返回值方法, 返回整型参数:"+num, Toast.LENGTH_LONG).show();
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myjnicalljava_MainActivity_native_1call_1java_1integer_1signature_1callBack_1method(
JNIEnv *env, jobject thiz)
// TODO: implement native_call_java_integer_signature_callBack_method()
LOGI("=========== native_call_java_integer_signature_callBack_method ===========");
jclass jcl = env->GetObjectClass(thiz);
jmethodID mid = env->GetMethodID(jcl, "callBack", "(I)V");
env->CallVoidMethod(thiz, mid, 145);
3.JNI 调用 Java 整型数组参数无返回值方法
public native void native_call_java_integerArray_signature_callBack_method();
public void callBack(int[] arr)
Toast.makeText(this, "调用java有参无返回值方法, 返回整型数组参数:"+arr[0]+","+arr[1]+","+arr[2], Toast.LENGTH_LONG).show();
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myjnicalljava_MainActivity_native_1call_1java_1integerArray_1signature_1callBack_1method(
JNIEnv *env, jobject thiz)
// TODO: implement native_call_java_integerArray_signature_callBack_method()
LOGI("=========== native_call_java_integer_signature_callBack_method ===========");
jclass jcl = env->GetObjectClass(thiz);
jmethodID mid = env->GetMethodID(jcl, "callBack", "([I)V");
jintArray newArr = env->NewIntArray(3);
int32_t a[3] = -145,82,74;
env->SetIntArrayRegion(newArr, 0, 3, a);
env->CallVoidMethod(thiz, mid, newArr);
jint* pnewArr = env->GetIntArrayElements(newArr, 0);
env->ReleaseIntArrayElements(newArr, pnewArr, 0);
4.JNI 调用 Java 字符串型参数无返回值方法
public native void native_call_java_string_signature_callBack_method();
public void callBack(String str)
Toast.makeText(this, "调用java有参无返回值方法, 返回字符串型参数:"+str, Toast.LENGTH_LONG).show();
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myjnicalljava_MainActivity_native_1call_1java_1string_1signature_1callBack_1method(
JNIEnv *env, jobject thiz)
// TODO: implement native_call_java_string_signature_callBack_method()
LOGI("=========== native_call_java_string_signature_callBack_method ===========");
jclass jcl = env->GetObjectClass(thiz);
// 注意括号里面有分号
jmethodID mid = env->GetMethodID(jcl, "callBack", "(Ljava/lang/String;)V");
std::string hello = "Hello from JNI";
env->CallVoidMethod(thiz, mid, env->NewStringUTF(hello.c_str()));
5.JNI 在子线程生成整型数组并回调 Java 整型数组参数无返回值方法
public native void native_thread_call_java_integerArray_signature_callBack_method();
public String str = "";
public void callBack(int[] arr, int length)
Log.e(TAG, "callBack: length = "+length);
for (int n : arr)
str+=", ";
str+=n;
runOnUiThread(
new Runnable()
@Override
public void run()
Toast.makeText(getApplicationContext(), "JNI在子线程生成整型数组并回调Java整型数组参数无返回值方法,JNI生成的整型数组为:"+str, Toast.LENGTH_LONG).show();
);
JavaVM* mVm = NULL;
jobject mObj = NULL;
void* native_thread_exec(void* args)
LOGI("=========== native_thread_exec ===========");
JNIEnv *env;
//从全局的JavaVM中获取到环境变量
mVm->AttachCurrentThread(&env,NULL);
jclass clazz = env->GetObjectClass(mObj);
jmethodID postID = env->GetMethodID(clazz,"callBack","([II)V");
jintArray newArr = env->NewIntArray(5);
int32_t a[5] = 415,789,654,-874,-842;
env->SetIntArrayRegion(newArr, 0, 5, a);
env->CallVoidMethod(mObj, postID, newArr, 5);
jint* pnewArr = env->GetIntArrayElements(newArr, 0);
env->ReleaseIntArrayElements(newArr, pnewArr, 0);
mVm->DetachCurrentThread();
pthread_exit(NULL);
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myjnicalljava_MainActivity_native_1thread_1call_1java_1integerArray_1signature_1callBack_1method(
JNIEnv *env, jobject thiz)
// TODO: implement native_thread_call_java_integerArray_signature_callBack_method()
LOGI("=========== native_thread_call_java_integerArray_signature_callBack_method ===========");
if (!mObj)
LOGI("=========== !mObj ===========");
mObj = env->NewGlobalRef(thiz);
//虽然JNI_OnLoad函数已经保存了JVM,但是那个没用.如果不调用env->GetJavaVM(&mVm); 会在线程中执行到myThreadProcessArray->mVm->AttachCurrentThread报错
env->GetJavaVM(&mVm);
pthread_t id;
//通过pthread库创建线程
LOGI("=========== create native thread ===========");
if(pthread_create(&id,NULL, native_thread_exec, NULL)!=0)
LOGI("=========== native thread create fail ===========");
return;
6.JNI 在子线程生成字节数组并回调 Java 字节数组参数无返回值方法,并写入文件
public native void native_thread_call_java_byteArray_signature_callBack_method();
public String str2 = "";
public void callBack_writeFile(byte[] barr, int length)
Log.e(TAG, "callBack: length = "+length);
for (byte b : barr)
str2+=b;
str2+=", ";
Log.e(TAG, "callBack_writeFile: "+str2 );
try
// 写入文件, 文件的路径在 /data/data/com.example.myjnicalljava/files/ 下面
FileOutputStream fout = openFileOutput("test.txt", MODE_PRIVATE);
fout.write(barr);
fout.close();
// 把刚才写入的内容,从文件中读出来
FileInputStream fin = openFileInput("test.txt");
byte[] readBuffer = new byte[length];
fin.read(readBuffer);
for (byte b : readBuffer)
Log.e(TAG, "callBack_writeFile readBuffer: "+b );
fin.close();
readBuffer = null;
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
Log.e(TAG, "callBack_writeFile: IOException" );
e.printStackTrace();
runOnUiThread(
new Runnable()
@Override
public void run()
Toast.makeText(getApplicationContext(), "JNI在子线程生成字节数组并回调Java字节数组参数无返回值方法,JNI生成的字节数组为:"+str2, Toast.LENGTH_LONG).show();
);
JavaVM* mVm = NULL;
jobject mObj = NULL;
void* native_thread_exec2(void* args)
LOGI("=========== native_thread_exec ===========");
JNIEnv *env;
//从全局的JavaVM中获取到环境变量
mVm->AttachCurrentThread(&env,NULL);
jclass clazz = env->GetObjectClass(mObj);
jmethodID postID = env->GetMethodID(clazz,"callBack_writeFile","([BI)V");
jbyteArray jbarray = env->NewByteArray(5);//建立jbarray数组
jbyte* pbarray = env->GetByteArrayElements(jbarray, NULL);
pbarray[0] = 5;
pbarray[1] = 9;
pbarray[2] = 2;
pbarray[3] = 3;
pbarray[4] = 4;
env->SetByteArrayRegion(jbarray, 0, 5, pbarray); //将Jbyte 转换为jbarray数组
env->CallVoidMethod(mObj, postID, jbarray, 5);
env->ReleaseByteArrayElements(jbarray, pbarray, 0);
mVm->DetachCurrentThread();
pthread_exit(NULL);
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myjnicalljava_MainActivity_native_1thread_1call_1java_1byteArray_1signature_1callBack_1method(
JNIEnv *env, jobject thiz)
// TODO: implement native_thread_call_java_byteArray_signature_callBack_method()
LOGI("=========== native_thread_call_java_byteArray_signature_callBack_method ===========");
if (!mObj)
LOGI("=========== !mObj ===========");
mObj = env->NewGlobalRef(thiz);
//虽然JNI_OnLoad函数已经保存了JVM,但是那个没用.如果不调用env->GetJavaVM(&mVm); 会在线程中执行到myThreadProcessArray->mVm->AttachCurrentThread报错
env->GetJavaVM(&mVm);
pthread_t id;
//通过pthread库创建线程
LOGI("=========== create native thread ===========");
if(pthread_create(&id,NULL, native_thread_exec2, NULL)!=0)
LOGI("=========== native thread create fail ===========");
return;
如果向pthread传递多个参数,可以将这多个参数封装在一个class里面,然后将这个class当作参数传递
以上是关于JNI调用Java方法的主要内容,如果未能解决你的问题,请参考以下文章
Android Studio NDK开发-JNI调用Java方法