文档章节

android使用c通过jni回调java

小飞有点不高兴
 小飞有点不高兴
发布于 2014/09/13 22:26
字数 684
阅读 13951
收藏 21

很多场合都有这样的需求,由于以前都是java调用c的接口,没有做过回调,今天花了大半天时间把这个流程跑通了,记录一下,以备后用。这里发句牢骚,那些网上分享出来的代码,请问你们确实是能正常工作吗?还有查来查去都是那几份,大家转载精神可嘉啊

jni相关头文件代码

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_example_ndktest_CallbackTest */

#ifndef _Included_com_example_ndktest_CallbackTest
#define _Included_com_example_ndktest_CallbackTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_ndktest_CallbackTest
* Method: start
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_ndktest_CallbackTest_start
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif




具体实现代码

 #include<stdlib.h>
#include<pthread.h>
#include<jni.h>
#include<android/log.h>
#include "com_example_ndktest_CallbackTest.h"
#define LOG_TAG "jni"


#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)


jmethodID mid;
jclass objclass;
jobject mobj;
pthread_t thread;
JavaVM *m_vm;


//初始化的时候会调进来一次,在这个方法里持有jvm的引用
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){
    m_vm=vm;
    JNIEnv* env = NULL;
    jint result = -1;
    if(m_vm){
        LOGD("m_vm init success");
    }else{
        LOGD("m_vm init failed");
    }
    if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK){
        return result;
    }
    return JNI_VERSION_1_4;
}
JNIEnv* getJNIEnv(int* needsDetach){
    JNIEnv* env = NULL;
    jint result = -1;
    if ((*m_vm)->GetEnv(m_vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK){
        int status = (*m_vm)->AttachCurrentThread(m_vm, &env, 0);
        if (status < 0){
            LOGD("failed to attach current thread");
            return NULL;
        }
        *needsDetach = 1;
    }
    LOGD("GetEnv Success");
    return env;
}


void *thread_run(){ 
    LOGD("thread start");
    int needsDetach;
    JNIEnv *evn=getJNIEnv(&needsDetach);
    LOGD("start noop callback");
    int i;
    for(i = 0; i < 100; i++){
        jstring jstr = (*evn) -> NewStringUTF(evn, "I am Fengfei");
        LOGD("invoke callback");
        (*evn)->CallVoidMethod(evn, mobj, mid, jstr);
        jthrowable exception = (*evn)->ExceptionOccurred(evn);
        if (exception) {
            (*evn)->ExceptionDescribe(evn);
        }
        sleep(2);
     }
    if(needsDetach)
        (*m_vm)->DetachCurrentThread(m_vm);
}


JNIEXPORT void JNICALL Java_com_example_ndktest_CallbackTest_start(JNIEnv *evn, jobject object){
LOGD("call start");


    //在子线程中不能这样用
    //jclass tclass = (*evn)->FindClass(evn, "com/example/ndktest/CallbackTest");

    //这种写法可以用在子线程中
    objclass=(*evn)->GetObjectClass(evn, object);
    mid = (*evn)->GetMethodID(evn, objclass, "callback", "(Ljava/lang/String;)V");

    //JNI 函数参数中 jobject 或者它的子类,其参数都是 local reference。Local reference 只在这个 JNI函数中有效,JNI函数返回后,引用的对象就被释放,它的生命周期就结束了。若要留着日后使用,则需根据这个 local reference 创建 global reference。Global reference 不会被系统自动释放,它仅当被程序明确调用 DeleteGlobalReference 时才被回收。(JNI多线程机制)
    mobj=(*evn)->NewGlobalRef(evn, object);
    pthread_create(&thread, NULL, thread_run, NULL);
}

java代码(具体怎么生成.so,参看android ndk使用)

package com.example.ndktest;

public class CallbackTest {

static {
    System.loadLibrary("callback");
}

public native void start();

public void callback(String str){
    System.out.println(str);
}

}



© 著作权归作者所有

小飞有点不高兴
粉丝 8
博文 1
码字总数 684
作品 2
成都
程序员
私信 提问
加载中

评论(5)

j
jack-S
我用reference = (*evn)->NewGlobalRef(evn, object);
当线程中Call时,出现如下崩溃信息:
JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xffffdf00
楼主知道为什么吗?
__8174__
__8174__

引用来自“小飞有点不高兴”的评论

引用来自“__8174__”的评论

这几天看别人代码这样用了,没办法jni是别人写的,必须要回调,过来学习了一下。感觉这样用违背了android架构的本意。你要等jni消息可以开个线程等不就好了。谢谢分享。

有些场景下可能需要jni回调,比如即时通信底层用c写的,收到消息后回调给上层
这样做效率会高点
小飞有点不高兴
小飞有点不高兴 博主

引用来自“__8174__”的评论

这几天看别人代码这样用了,没办法jni是别人写的,必须要回调,过来学习了一下。感觉这样用违背了android架构的本意。你要等jni消息可以开个线程等不就好了。谢谢分享。

有些场景下可能需要jni回调,比如即时通信底层用c写的,收到消息后回调给上层
__8174__
__8174__
这几天看别人代码这样用了,没办法jni是别人写的,必须要回调,过来学习了一下。感觉这样用违背了android架构的本意。你要等jni消息可以开个线程等不就好了。谢谢分享。
c
cdmar79
网上的代码也能全信,呵呵!给个框架而已,你还是要自己调试的
关于native层回调java层

1、关于jni调用种种情形的分析,可以参考一下如下网址中的文章:http://android.wooyd.org/JNIExample/ 2、native层回调java层: native层没有自己的线程,只是在java调用native代码,nativ...

LiSteven
2013/03/30
147
0
Android JNI与NDK编程

导语 Java JNI本意为Java Native Interface(java本地接口), 是为方便java调用C或者C++等本地代码所封装的一层接口. 由于Java的跨平台性导致本地交互能力的不好, 一些和操作系统相关的特性Jav...

一个有故事的程序员
05/30
0
0
NDK开发笔记之2:AndroidStudio3.3+Cmake+JNA例子

1 参考 Java本地接口 Android NDK官方文档 JNI的替代者—使用JNA访问Java外部功能接口 GitHub:java-native-access/jna 2 JNI与JNA 2.1 JNI (本地接口)是一种编程框架,使得Java虚拟机中的J...

newtrek
06/05
0
0
android JNI使用方法

经过几天的努力终于搞定了android JNI部分,下面将我的这个小程序和大家分享一下。android JNI是连接android Java部分和C/C++部分的纽带,完整使用JNI需要Java代码和C/C++代码。其中C/C++代码...

linuxhunter
2011/12/26
3.9K
2
JNI和NDK的区别

NDK(Native Development Kit)“原生”也就是二进制 android常用的开发方式是java封装的库,而这些库的底层实现是由C/C++实现,如媒体,图形库等 java调用这样实现就需要用JNI(Java Native...

长平狐
2013/01/06
123
0

没有更多内容

加载失败,请刷新页面

加载更多

c++运算符重载

这个运算符重载觉得有点像java的装箱 #ifndef INTERGER_H #define INTERGER_H //学习下运算符的重载 class Interger { public: Interger(); Interger(int value):m_value(value){}......

南桥北木
27分钟前
4
0
微信公众号如何推送文章

公众号推送消息格式,可以推送文本、图文消息、小程序、优惠券、会员卡、图片、视频、语音,不仅仅只能推送文章即图文消息,支持素材永久链接,表情符号等。 通过公众号接口可以开发各种各样...

保持美好
28分钟前
4
0
云桌面经常被吐槽,为什么还有很多人在用

说起云桌面我们会发现一个很奇怪的现象,那就是我们在网上经常能看到有人在吐槽云桌面的,说云桌面的性能差、价格贵和各种的不好用。虽然说网上有很多人都在吐槽云桌面,但是我们会发现使用它...

GZASD
35分钟前
5
0
支付宝20积分兑换15天会员

支付宝20积分兑换30天会员 活动地址:https://openact.ximalaya.com/alipay-vip/#/(或支付宝扫码打开)

xiaogg
38分钟前
6
0
DDoS攻击是怎么打垮游戏企业的?

1.占用服务器的有限资源。比如TCP连接数资源(服务器的连接数是有限制的),有的TCP连接会断开,有的会保持通信;比如一家餐馆,攻击者打比方是地痞流氓总是去排队,但是并不去消费,那么此时正...

云漫网络Ruan
39分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部