마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

C에서 JAVA 메소드 호출 문의드립니다..

0 추천

안녕하세요.

자바는 아래와 같이..  testCallback() 메소드가 있습니다. C에서 콜하면 어떤 동작을 하게 만들 함수이고요.. public static void testCallback() { 

  //String param Log.e("testCallback""vvvvvv");

}

네이티브 쪽은, 아래와 같이 되어있습니다.

JNIEnv* getJNIEnv(JavaVM* jvm)
{

    if (NULL == jvm) {
//        LOGD("Failed to get JNIEnv. JniHelper::getJavaVM() is NULL");
        return NULL;
    }

    JNIEnv *env = NULL;
    // get jni environment
    jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);

    switch (ret) {
        case JNI_OK :
            // Success!
            return env;

        case JNI_EDETACHED :
            // Thread not attached

            // TODO : If calling AttachCurrentThread() on a native thread
            // must call DetachCurrentThread() in future.
            // see: http://developer.android.com/guide/practices/design/jni.html

            if (jvm->AttachCurrentThread(&env, NULL) < 0)
            {
//                LOGD("Failed to get the environment using AttachCurrentThread()");
                return NULL;
            } else {
                // Success : Attached and obtained JNIEnv!
                return env;
            }

        case JNI_EVERSION :
            // Cannot recover from this error
//            LOGD("JNI interface version 1.4 not supported");
        default :
//            LOGD("Failed to get the environment using GetEnv()");
            return NULL;
    }
}

// get class and make it a global reference, release it at endJni().
jclass getClassID(JNIEnv *pEnv, const char* className)
{
    jclass ret = pEnv->FindClass(className);
    if (! ret)
    {
//        LOGD("Failed to find class of %s", className);
    }

    return ret;
}
bool getStaticMethodInfo(JavaVM* jvm, JniMethodInfo &methodinfo, const char* className, const char *methodName, const char *paramCode)
{
    jmethodID methodID = 0;
    JNIEnv *pEnv = 0;
    bool bRet = false;

    do
    {
        pEnv = getJNIEnv(jvm);
        if (! pEnv)
        {
            break;
        }

        jclass classID = getClassID(pEnv, className);

        methodID = pEnv->GetStaticMethodID(classID, methodName, paramCode);
        if (! methodID)
        {
//            LOGD("Failed to find static method id of %s", methodName);
            break;
        }

        methodinfo.classID = classID;
        methodinfo.env = pEnv;
        methodinfo.methodID = methodID;

        bRet = true;
    } while (0);

    return bRet;
}
void callback(JavaVM* jvm, const char* value){
    JniMethodInfo methodInfo;

    __android_log_print(ANDROID_LOG_INFO
            , "callback"
            , "%s:%d :: Log "
            , __FUNCTION__
            , __LINE__);

    //Ljava/lang/String;
    if (! getStaticMethodInfo(jvm, methodInfo, "nex/sample/myapplication/MainActivity", "testCallback", "()V"))
    {
        return;
    }

    jstring stringArg = methodInfo.env->NewStringUTF(value);
    methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg);
    methodInfo.env->DeleteLocalRef(stringArg);
    methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
 
이게 끝입니다.. 구글링하면 흔하게 나온 소스를 제 경로에 맞게 수정해서 사용했습니다.. testCallback() 를 호출 하려고 했으나 , 
if (! getStaticMethodInfo(jvm, methodInfo, "nex/sample/myapplication/MainActivity", "testCallback", "()V"))
{
    return;
} // 여기에서 return;  되더라구요...;;; 몇일째 찾아봐도 샘플을 따라해도 해결이 되질않아서 질문드립니다 ㅜ 잘 못된 부분좀 도와주세요.. 
꾸우우 (1,140 포인트) 님이 2018년 2월 19일 질문

1개의 답변

+1 추천
 
채택된 답변

인터넷에 올라와 있는 코드를 써서 당연한거겠지만.. 

메소드를 찾는 부분까지 호출하는 코드에서는 특별한 문제가 안 보입니다. 

 

말씀 해주신 부분에서 반환되는 경우는

1. void callback 의 입력값인 jvm 이 null 일경우

2.  pEnv = getJNIEnv(jvm); 을 통해 반환하는 pEnv가 null 일 경우

3. public static void testCallback()  메소드가 있는 경로가 nex/sample/myapplication/MainActivity 가 아닐 경우 일듯 한데.. 확인 해 보세요..

 

그리고 메소드를 찾더라도 

methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg); 로 호출 하는데, 실제 메소드의 입력값은 void라. 오류 날 듯 합니다.

methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID); 로 호출하시던지.

 

아래와 같이 고쳐주셔야 string 데이터가 java로 전달 될 듯 합니다.

java 쪽의 경우

public static void testCallback(String message) {

  // Log.e("testCallback", message​);

}

c쪽에서 메소드 찾는 부분의 경우

  if (! getStaticMethodInfo(jvm, methodInfo, "nex/sample/myapplication/MainActivity", "testCallback", "(Ljava/lang/String;)V")){}

 

 

 

 

사악미소 (65,330 포인트) 님이 2018년 2월 19일 답변
꾸우우님이 2018년 2월 19일 채택됨
감사합니다..ㅜㅠ
역시 잘 아시는분이 한마디 해주시면 해결이 턱턱되네요 ㅜㅠ
일주일을 끙끙앓았는데 깔끔하게 해결이 되서 정말 기쁩니다!
...