在NDK C++线程中如何调用JAVA API

时间:2023-11-26 13:09:20

from://http://www.eoeandroid.com/thread-150995-1-1.html

在NDK中创建的线程中, 只允许调用静态的Java API. 当在线程中调用env->FindClass(), 系统就会发出异常.
http://android.wooyd.org/JNIExample中有较详细的调用说明.

示例代码如下:

JAVA 代码:
public class simple_test extends Activity {
    ...
    public static void PrintNdkLog(String slog) {
        Log.e("NDK", slog);
    }
}
        
C++ 代码:

static JavaVM* g_JavaVM = NULL;
static jobject g_InterfaceObject = 0;

static void GetInterfaceObject(JNIEnv *env, const char *path, jobject *objptr) {
    jclass cls = env->FindClass(path);
    if(!cls) {
        return;
    }
    jmethodID constr = env->GetMethodID(cls, "<init>", "()V");
    if(!constr) {
        return;
    }
    jobject obj = env->NewObject(cls, constr);
    if(!obj) {
        return;
    }
    (*objptr) = env->NewGlobalRef(obj);
}

int JniLoad(JavaVM* jvm, void* reserved)
{
    g_JavaVM = jvm;

JNIEnv *env;
    if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }

GetInterfaceObject(env, "com/myndk/simple_test", &g_InterfaceObject);
    return JNI_VERSION_1_6;
}

void JniUnLoad(JavaVM* jvm, void* reserved)
{
    JNIEnv *env;
    if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) {
        return;
    }

env->DeleteGlobalRef(g_InterfaceObject);
}

void PrintNdkLog(const char *format, ...)
{
    va_list arg_ptr;
    char sLogBuff[1024];

va_start(arg_ptr, format);
    vsprintf(sLogBuff, format, arg_ptr);
    va_end(arg_ptr);

if (g_JavaVM == NULL)
        return;

int status;
    JNIEnv *env = NULL;
    bool isAttached = false;

status = g_JavaVM->GetEnv((void**) &env, JNI_VERSION_1_6);
    if(status < 0)
    {
        status = g_JavaVM->AttachCurrentThread(&env, NULL);
        if(status < 0)
        {
            return;
        }
        isAttached = true;
    }

jclass cls = env->GetObjectClass(g_InterfaceObject);
    if (cls != 0)
    {
        jmethodID mid = env->GetStaticMethodID(cls, "PrintNdkLog", "(Ljava/lang/String;)V");
        if (mid != 0)
        {
            jstring jstrMSG = env->NewStringUTF(sLogBuff);
            env->CallStaticVoidMethod(cls, mid, jstrMSG);
        }
    }

if (isAttached)        // From native thread
    {
        g_JavaVM->DetachCurrentThread();
    }
}