博客
关于我
android jni c++线程创建 c++回调java{主线程/子线程}
阅读量:258 次
发布时间:2019-03-01

本文共 8074 字,大约阅读时间需要 26 分钟。

首先更新一些知识点

1、根据jobject获取jclass(静态方法就不用这一步了)如:jclass clz = env->GetObjectClass(jobj);
获取jmethodid如: jmethodid  jmid = 		env->GetMethodID(clz, "onError", "(ILjava/lang/String;)V")
3、调用方法如: jenv->CallVoidMethod(jobj, jmid, code, jmsg) 

       由于JniEnv是线程相关的,所以子线程中不能使用创建线程的JniEnv;而 JVM是进程相关的,所以可以通过JVM来获取当前线程的JniEnv,然后就可以 调用Java的方法了。 

1、获取JVM对象: JNI_OnLoad(JavaVM* vm,void* reserved)
2、通过JVM获取JniEnv:        JNIEnv *env;          jvm->AttachCurrentThread(&env, 0);        /*	      call Java Methoid        */         jvm->DetachCurrentThread();

接下来上代码

xml

mainactivity

package com.example.jnithread;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;public class MainActivity extends AppCompatActivity {    ThreadDemo mThreadDemo;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mThreadDemo = new ThreadDemo();        mThreadDemo.setmOnErrorListener(new ThreadDemo.OnErrorListener() {            @Override            public void onError(int code, String msg) {                Log.i("godv", "code :" + code + "msg:" + msg);            }        });    }    public void run(View view) {        mThreadDemo.startThread();    }    public void buy(View view) {        mThreadDemo.startBuyThread();    }    public void callJavaMain(View view) {        mThreadDemo.cCallBackJava();    }}

ThreadDemo

package com.example.jnithread;public class ThreadDemo {    static {        System.loadLibrary("native-lib");    }    public native void startThread();    public native void startBuyThread();    public native void cCallBackJava();    //    public void onError(int code, String msg) {        if (mOnErrorListener != null) {            mOnErrorListener.onError(code, msg);        }    }    public interface OnErrorListener {        void onError(int code, String msg);    }    private OnErrorListener mOnErrorListener;    public void setmOnErrorListener(OnErrorListener mOnErrorListener) {        this.mOnErrorListener = mOnErrorListener;    }}

nativelib-cpp

#include 
#include
#include "GodvLog.h"//线程的头文件#include "pthread.h"//线程的变量pthread_t thread;//线程的回调 也就是真正执行的函数void *mycallBack(void *data) { LOGD("GODV create thread in c++"); //销毁线程 pthread_exit(&thread);}//普通线程extern "C"JNIEXPORT void JNICALLJava_com_example_jnithread_ThreadDemo_startThread(JNIEnv *env, jobject thiz) { //创建线程的api pthread_create(&thread, NULL, mycallBack, NULL);}//队列的头文件#include "queue"//sleep的头文件#include "unistd.h"//消费者线程pthread_t buy;//消费者线程pthread_t sell;//线程锁pthread_mutex_t mutex;//线程信号pthread_cond_t cond;bool tag = true;//创建队列std::queue
queue;void *buyCallBack(void *data) { while (tag) { //线程锁 pthread_mutex_lock(&mutex); if (queue.size() > 0) { queue.pop(); LOGD("消费者消费了一个产品,目前产品总数为:%d", queue.size()); } else { LOGD("消费者正在等待。。。"); //线程等待 同时释放线程锁 pthread_cond_wait(&cond, &mutex); } //线程解锁 pthread_mutex_unlock(&mutex); usleep(1000 * 500); } pthread_exit(&buy);}void *sellCallBack(void *data) { while (tag) { //线程锁 pthread_mutex_lock(&mutex); queue.push(1); LOGD("生产者生产了一个产品,并通知消费者可以消费了,目前产品总数为:%d", queue.size()); //发送信号激活等待的线程 pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); sleep(5); } pthread_exit(&sell);}//生产者消费者线程extern "C"JNIEXPORT void JNICALLJava_com_example_jnithread_ThreadDemo_startBuyThread(JNIEnv *env, jobject thiz) { for (int i = 0; i < 10; i++) { queue.push(i); } //初始化线程锁 pthread_mutex_init(&mutex, NULL); //初始化线程通知 pthread_cond_init(&cond, NULL); pthread_create(&buy, NULL, buyCallBack, NULL); pthread_create(&sell, NULL, sellCallBack, NULL);}#include "JavaListener.h"JavaVM *jvm;JavaListener *javaListener;pthread_t childThread;void *childCallBack(void *data) { JavaListener *childjavaListener = (JavaListener *) data; sleep(5); childjavaListener->onError(1, 200, "godv c++ call java child thread"); pthread_exit(&childThread);}extern "C"JNIEXPORT void JNICALLJava_com_example_jnithread_ThreadDemo_cCallBackJava(JNIEnv *env, jobject thiz) { //此处jobj需要处理成全局的这样子线程主线程都能用 javaListener = new JavaListener(jvm, env, env->NewGlobalRef(thiz)); //主线程调用 javaListener->onError(0, 100, "godv c++ call java main thread"); //第二个NULL用作childCallBack的data pthread_create(&childThread, NULL, childCallBack, javaListener);}JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *unused) { JNIEnv *env; jvm = vm; if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { return -1; } return JNI_VERSION_1_6;}

c++ call java 的类

GCallJava.h

#ifndef RTMPSUC_GCALLJAVA_H#define RTMPSUC_GCALLJAVA_H#include "jni.h"#define G_THREAD_MAIN 1#define G_THREAD_CHILD 2class GCallJava {public:    JNIEnv *jniEnv = NULL;    JavaVM *javaVm = NULL;    jobject jobj;    jmethodID jmid_connecting;public:    GCallJava(JavaVM *javaVm, JNIEnv *jniEnv, jobject *jobj);    ~GCallJava();    void onConnecting(int type);};#endif //RTMPSUC_GCALLJAVA_H

GCallJava.cpp

#include "GCallJava.h"GCallJava::GCallJava(JavaVM *javaVm, JNIEnv *jniEnv, jobject *jobj) {    this->javaVm = javaVm;    this->jniEnv = jniEnv;    this->jobj = jniEnv->NewGlobalRef(*jobj);    jclass jlz = jniEnv->GetObjectClass(this->jobj);    jmid_connecting = jniEnv->GetMethodID(jlz, "onConnecting", "()V");}GCallJava::~GCallJava() {    jniEnv->DeleteGlobalRef(jobj);    javaVm = NULL;    jniEnv = NULL;}void GCallJava::onConnecting(int type) {    if (type == G_THREAD_CHILD) {        JNIEnv *jniEnv;        if (javaVm->AttachCurrentThread(&jniEnv, 0) != JNI_OK) {            return;        }        jniEnv->CallVoidMethod(jobj, jmid_connecting);        javaVm->DetachCurrentThread();    } else {        jniEnv->CallVoidMethod(jobj, jmid_connecting);    }}

 native-lib.cpp

#include 
#include
#include "RtmpPush.h"/********************************************************回调***************************************/#include "GCallJava.h"GCallJava *gCallJava = NULL;JavaVM *javaVm = NULL;/********************************************************回调***************************************/RtmpPush *rtmpPush = NULL;extern "C"JNIEXPORT void JNICALLJava_com_example_glivepush_push_PushVideo_initPush(JNIEnv *env, jobject thiz, jstring pushUrl_) { // TODO: implement initPush() const char *pushUrl = env->GetStringUTFChars(pushUrl_, 0); /********************************************************回调***********************************/ gCallJava = new GCallJava(javaVm, env, &thiz); rtmpPush = new RtmpPush(pushUrl, gCallJava); /********************************************************回调***********************************/ rtmpPush->init(); env->ReleaseStringUTFChars(pushUrl_, pushUrl);}/********************************************************回调***************************************/extern "C"JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; javaVm = vm; if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { return -1; } return JNI_VERSION_1_6;}extern "C"JNIEXPORT void JNICALLJNI_OnUnload(JavaVM *vm, void *reserved) { javaVm = NULL;}/********************************************************回调***************************************/

 androidlog

//// Created by guosy on 20-10-15.//#ifndef GODVMUSIC_GODVLOG_H#define GODVMUSIC_GODVLOG_H#endif //GODVMUSIC_GODVLOG_H#include "android/log.h"#define LOG_TAG "godv"#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)add_library(             native-lib             SHARED           ${CMAKE_SOURCE_DIR}/src/main/cpp/native-lib.cpp           ${CMAKE_SOURCE_DIR}/src/main/cpp/JavaListener.cpp            )target_link_libraries(                        native-lib                        log )

 

转载地址:http://ebzo.baihongyu.com/

你可能感兴趣的文章
“上者劳智,中者劳人,下者劳力;小富由勤,大富由命,巨富由恶”
查看>>
庄子:谁知南华秋水意?
查看>>
【Kotlin开发者社区文章集锦】66篇精选技术精华文章
查看>>
关于Spring的事务Transactional,锁同步,并发线程
查看>>
android 在一个应用中启动另一个应用
查看>>
Thread.sleep() 和 Thread.yield() 区别
查看>>
Kotlin 简单优雅的高阶函数
查看>>
ES6 箭头函数: () => {} 与匿名函数 function() {}
查看>>
13.13 java.util.ConcurrentModificationException
查看>>
UML类图关系(泛化 、继承、实现、依赖、关联、聚合、组合)
查看>>
第14章 使用Kotlin 进行 Android 开发(2)
查看>>
Spring Boot 2.0 与 Spring 5 项目实战开发(基于 Kotlin & Java )
查看>>
第1讲 快速入门 《Kotlin 极简教程 》
查看>>
《拾叶集》一个会写诗的程序员 二零一八年十月九日
查看>>
Spring Data JPA WITH Kotlin
查看>>
《程序设计课》第20181009期 ——一个会写诗的程序员
查看>>
Kotlin + Spring Boot :下一代 Java 服务端开发 (视频)
查看>>
图书推荐:Kotlin从入门到进阶实战
查看>>
《Spring Boot 2.0 极简教程》附录 I : Spring 5.0 新特性
查看>>
IDEA 工程文件 UTF-8 编码设置
查看>>