android jni 结构体_Android应用开发Android JNI-c/c++调用java方法

本文将带你了解Android应用开发Android JNI-c/c++调用java方法,希望本文对大家学Android有所帮助。

"

Android   JNI-c/c++调用java方法,在使用ndk开发的时候,java调用c/c++方法是必须要的。但是很多时候,c/c++有callback需要反馈给java的时候(比如IM通讯登录成功信息和一些异常信息),就需要c/c++调用java方法了。

在看这篇文章之前,必须对JNI有一些基础的了解,比如java调用c/c++方法,java和c/c++   jni在一些基本类型上的对应(int对应jint等)。

那么现在介绍一下c/c++调用java方法的基本步骤:

1.需要把java方法所在类的实例通过JNI方法传到c/c++

java:JNI, 这是c需要回调的java方法,然后通过调用自身init()方法,把java实例传到c层

?

1

2

3

4

5

6

class JNI {

public native void init(JNI obj);

public void error(int code) {

Log.i(""JNI"", ""c++ call error   "");

}

}

c:这里把java传递进来的objListener,保存到c的jniobj结构体内。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

JNIEXPORT jint JNICALL Java_com_arcvideo_rtcmessage_JNI_init(

JNIEnv *env,

jobject oj,

jobject objListener,

)

{

if(objListener == MNull){

MVLOG(""objListener is null"");

}else

{

MVLOG(""get   java obj"");

jniobj->g_obj =   env->NewGlobalRef(objListener);

}

return res;

}

typedef struct _tagJNIObj{//这个是刚才保存java实例的结构体,在还有其他参数

jmethodID JNI_error;

JavaVM* g_jvm;

JNIEnv* g_ThreadEnv;

jclass g_class;

jobject g_obj;

MHandle g_h;

}JNIObj;

static JNIObj* jniobj = MNull;

2.在c层拿到java class

c:通过jni提供的FindClass方法和完整类名,可以拿到class引用

?

1

2

static const char* const DL_CLASS_NAME =   ""com/arcvideo/rtcmessage/JNI"";

jniobj->g_class = env->FindClass(DL_CLASS_NAME);

3.在c层拿到java method

c:根据刚才拿到的java class引用有jni提供的GetMethodID方法,和方法名,入参,就可以拿到method引用

?

1

2

3

4

5

6

// error

jniobj->JNI_error =   env->GetMethodID(jniobj->g_class, ""error"",

""(I)V"");

if(jniobj->JNI_error ==   MNull){

MVLOG(""create   JNI_error is error"");

}

4.调用method

c:在需要调用的地方调用这个java方法,

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

static void error(MDWord code, MVoid* pObj)

{

MVLOG(""RtcMessageJNI   error is in code : %d"", code );

if(jniobj->g_ThreadEnv ==   MNull)

{

MVLOG(""attach   current thread start"");

jniobj->g_jvm ->   AttachCurrentThread(&jniobj->g_ThreadEnv, MNull);

if(jniobj->g_ThreadEnv ==   MNull){

MVLOG(""attach   current thread is error"");

return;

}

}

if(jniobj &&   jniobj->JNI_error){

MVLOG(""RtcMessageJNI error is called"");

//这里是最关键的调用过程,通过JNI提供的CallVoidMethod,来调用,加入参数,class引用,method应用,已经入参,这样调用java方法就完成了。

jniobj->g_ThreadEnv->CallVoidMethod(jniobj->g_obj,   jniobj->JNI_error,

(int)code);

}

if(jniobj->g_jvm){

MVLOG(""RtcMessageJNI error method   detach"");

jniobj->g_jvm->DetachCurrentThread();

jniobj->g_ThreadEnv =   MNull;

}

}

这里在调用java方法的时候调用了,AttachCurrentThread和DetachCurrentThread方法,这是必须的,如果不调用AttachCurrentThread就拿不到线程的引用,会报错误。然后在调用结束的时候要调用DetachCurrentThread,也就是释放线程。根据个人经验,最好每次调用java方法结束的时候都调用DetachCurrentThread,这样基本不会出错。

"

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值