Linux线程通过JNI回调JAVA函数

最近做的一个小工程需要用到回调函数,由linux层回调到java层,调试的时候会遇到一些问题,免得忘记,在这里记录一下:

JNI的各种数据类型和数据结构我就不详细介绍了,简单说一下

JavaVM *m_jvm;  java虚拟机,这个变量可以在不同的线程里面使用,获取的方法也有很多,可以通过env获取,也可以通过JNI_OnLoad函数来获取

JNIEnv *g_env;     这个是一个线程的相关变量,这里注意的是一个线程的,对于每个线程来说是唯一的,不能在不同的线程里面使用同一个env;

jobject g_obj;        因为java层的代码,native的接口和主activity不是放在同一个class里面,因此把主activity的obj传下来的,方便在JNI层更快的寻找到activity的class

jclass g_class;     为之前的g_obj里面的类对象

int flagthread = 0;  因为特殊原因,我的代码里面的第一个线程为UI线程,之后的线程由底层创建,因为设置一个flag来过滤第一个线程,方便之后的attach和detach

接下去就是上代码了

这是一个回调函数,给linux用的,上报状态的,在代码已经注明了必须attach,不然会报以下错误

E/dalvikvm( 2068): JNI ERROR: non-VM thread making JNI calls

E/dalvikvm( 2068): VM aborting

F/libc    ( 2068): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 2125 (id.wifimiracast)

其实也很好理解,因为大家注意到我的接口并不是标准的JNI接口,这个接口是我自己创建供linux层回调的,一般标准的JNI接口,是直接供java层使用的,那时候的多线程attach其实是attach到UI线程上的,但在linux里面创建了一个线程去回调这个状态函数的时候,并没有涉及到UI线程,所以是到了JNI层的话,必须也得要有一个线程去处理这个回调,下面的就好理解了,JNI线程去回调java的时候,java也必须要有一个线程去处理,下面会讲到。

在代码里面可以看到我调用的是statebroadcast这个回调函数

这里必须要用handler去处理,不然会报如下错误

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

at android.os.Handler.(Handler.java:121)

at com.cao.android.demos.handles.HandleTestActivity$MyThread$1.(HandleTestActivity.java:86)

at com.cao.android.demos.handles.HandleTestActivity$MyThread.run(HandleTestActivity.java:86)

这样从linux线程通过JNI调用到JAVA的函数就完全可以啦,第一次作记录,如果 有错误,欢迎斧正!