推荐阅读: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当作参数传递