本文主要是介绍linux+ndk把jni制作成so库供apk使用(带线程的回调),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
我们就不墨迹了,直接开始,往往我们需要jni给我们回调一些数据,并且是实时的回调,这里我们就需要多写一些东西了
1.先在安卓里面设置好接口以及回调,我自己给你们看源代码
package com.example.myndkapplicationimport android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*class MainActivity : AppCompatActivity() {// java回调接口 INativeListener.javainterface INativeListener {fun onCall(str:String)}external fun nativeCallBack(callBack: INativeListener?)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)Log.e("TAG","nativeCallBack================onCreate")nativeCallBack(object : INativeListener {override fun onCall(str: String) {Log.e("TAG","nativeCallBack================onCall()====$str")runOnUiThread { sample_text.text = str }}})stringFromJNI()}external fun stringFromJNI()companion object {// Used to load the 'native-lib' library on application startup.init {System.loadLibrary("test")}}
}
2.我们再来修改jni里面的test.c
这里我们新增了一个线程pthread,一个Java_com_example_myndkapplication_MainActivity_nativeCallBack方法,以及JNI_OnLoad虚拟机环境方法
JNI_OnLoad这个方法不需要任何调用,在jni跑起来以后会自动运行
Android JNI 规定,在非主线程中调用 JNI 函数时需要先通过
AttachCurrentThread
方法将当前线程附加到 Java 虚拟机上,以确保 JNI 调用的上下文正确。
#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/time.h>
#include <android/log.h>
#define TAG "TAG" // 指定您的日志标签//##########################################################新增内容#######################################################include <pthread.h> // 包含线程相关的头文件// 全局变量,用于存储 Java 虚拟机环境
JavaVM *g_jvm = NULL;
jobject global_callback = NULL;
jmethodID gCallBackMid;
JNIEnv *env;void *thread_function(void *arg) {// 将当前线程附加到Java虚拟机上,获取JNIEnv指针if ((*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL) != JNI_OK) {// 获取JNIEnv失败return NULL;}while (true) {// 在这里执行你的应用逻辑,生成新的 ch 数据jstring jstr = (*env)->NewStringUTF(env, "write success");// 回调到java层(*env)->CallVoidMethod(env, global_callback, gCallBackMid, jstr);// 释放本地引用(*env)->DeleteLocalRef(env, jstr);// 等待一段时间,比如 1 秒sleep(1); // 单位是秒}// 将当前线程从Java虚拟机上分离(*g_jvm)->DetachCurrentThread(g_jvm);return NULL;
}// JNI 初始化函数,保存 Java 虚拟机环境
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {g_jvm = vm; // 保存 Java 虚拟机环境到全局变量 g_jvmreturn JNI_VERSION_1_6;
}// JNI 回调函数,保存回调对象
JNIEXPORT void JNICALL
Java_com_example_myndkapplication_MainActivity_nativeCallBack(JNIEnv *env, jobject thiz, jobject call_back) {// 创建一个 JNI 全局引用global_callback = (*env)->NewGlobalRef(env, call_back);// 获取回调方法的方法IDjclass cls = (*env)->GetObjectClass(env, call_back);gCallBackMid = (*env)->GetMethodID(env, cls, "onCall", "(Ljava/lang/String;)V");__android_log_print(ANDROID_LOG_DEBUG, TAG, "Java_com_example_myndkapplication_MainActivity_nativeCallBack\n"); // 创建新线程并启动pthread_t thread;pthread_create(&thread, NULL, thread_function, NULL);
}//######################################################################################################################################JNIEXPORT jstring JNICALL
Java_com_example_myndkapplication_MainActivity_stringFromJNI(JNIEnv *env, jobject obj) {__android_log_print(ANDROID_LOG_DEBUG, TAG, "test_begain\r\n: %s", "===========stringFromJNI=======1======");//pthread_t thread;//pthread_create(&thread, NULL, start_app, NULL);__android_log_print(ANDROID_LOG_DEBUG, TAG, "test_end\r\n: %s", "===========stringFromJNI=======2======");return (*env)->NewStringUTF(env, "===========stringFromJNI=======3======");
}
3.运行并生成so库供apk使用
然后就可以看到jni在一直发送消息给安卓界面
这篇关于linux+ndk把jni制作成so库供apk使用(带线程的回调)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!