albon arith

一些总结,欢迎交流

Android NDK: 子线程中C调用Java

在底层c++生成的子线程中调用Java,需要JniEnv。而这个JniEnv的生成,需要用AttachCurrentThread方法。

1. 获取JVM,以及静态方法实例
static JavaVM* g_JavaVM = NULL;
static jobject gInterfaceObject;

void initClassHelper(JNIEnv *env, const char *path, jobject *objptr) {
    jclass cls = env->FindClass(path);
    if(!cls) {
        LOGE("initClassHelper: failed to get %s class reference", path);
        return;
    }
    jmethodID constr = env->GetMethodID(cls, "<init>", "()V");
    if(!constr) {
        LOGE("initClassHelper: failed to get %s constructor", path);
        return;
    }
    jobject obj = env->NewObject(cls, constr);
    if(!obj) {
        LOGE("initClassHelper: failed to create a %s object", path);
        return;
    }
    (*objptr) = env->NewGlobalRef(obj);
}


JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
    g_JavaVM = vm;
    JNIEnv *env = NULL;
int status = g_JavaVM->GetEnv((void **) &env, JNI_VERSION_1_6);
if (status < 0) {
LOGE("get env failure");
return JNI_VERSION_1_6;
}
initClassHelper(env, "com/iptv/epg/Inform", &gInterfaceObject);
    return JNI_VERSION_1_6;
}

根据g_JavaVM可以得到JniEnv,根据gInterfaceObject可以得到相应的class。

2. 在子线程中调用Java方法
下面的代码与1中代码处于不同线程。
JNIEnv *jniEnv = NULL;
bool isAttached = false;
//获取env
int status = g_JavaVM->GetEnv((void **) &jniEnv, JNI_VERSION_1_6);
if(status < 0) {
__android_log_print(ANDROID_LOG_INFO, "SuIPTV", "[%s] failed to get JNI environment", __FUNCTION__);
//如果是在子线程中,应该以AttachCurrentThread获取env
status = g_JavaVM->AttachCurrentThread(&jniEnv, NULL);
if(status < 0) {
LOGE("callback_handler: failed to attach current thread");
return;
} else {
isAttached = true;
LOGE("callback_handler: ttach current thread success");
}
//获取对应class
jclass InformProvider = jniEnv->GetObjectClass(gInterfaceObject);
if(!InformProvider) {
LOGE("callback_handler: failed to get class reference");
if(isAttached) g_JavaVM->DetachCurrentThread();
return;
} else {
LOGE("callback_handler: get class reference success");
}
//获取静态方法
jmethodID playEnd = jniEnv->GetStaticMethodID(InformProvider, "playEnd","()V");
if(!playEnd) {
LOGE("callback_handler: failed to get method ID");
if(isAttached) g_JavaVM->DetachCurrentThread();
return;
} else {
LOGE("callback_handler: get method ID success");
}
//调用Java方法
jniEnv->CallStaticObjectMethod(InformProvider, playEnd);
if(isAttached) g_JavaVM->DetachCurrentThread();
__android_log_print(ANDROID_LOG_INFO, "SuIPTV", "[%s] CallStaticObjectMethod", __FUNCTION__);
3. 被调用的Java方法如下
public class Inform {

public static void playEnd() {

}
}

另外,利用javap生成方法签名:
阅读更多

扫码向博主提问

去开通我的Chat快问

hustspy1990

博客专家

顺其自然
  • 擅长领域:
  • Java
  • 性能优化
  • 系统设计
  • 高可用
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hustspy1990/article/details/8915443
个人分类: C/C++ Android
上一篇Ubuntu下安装Hadoop和配置Eclipse开发Hadoop
下一篇Android:获取屏幕完整宽高,包含状态栏
想对作者说点什么? 我来说一句

Android studio NDK,JNI开发

2016年10月10日 11.32MB 下载

Android NDK Java 调用C

2011年09月26日 76KB 下载

没有更多推荐了,返回首页

关闭
关闭