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生成方法签名:
http://www.blogjava.net/lihao336/archive/2011/10/24/361901.html

你可能感兴趣的:(Android NDK: 子线程中C调用Java)