How to create callbacks between android code and native code?

前端 未结 2 339
醉梦人生
醉梦人生 2020-12-29 14:39

I have a requirement for creating call backs between native code ( c language code) and Android code . I wrote JNI functions for calling C code from the androi

2条回答
  •  醉梦人生
    2020-12-29 15:04

    From java code:

    public static void callback(String value){
        Log.e(TAG, "value:"+value);
     }
    

    And call in C:

    typedef struct JniSMSMethodInfo
    {
        JNIEnv *    env;
        jclass      classID;
        jmethodID   methodID;
    } JniMethodInfo;
    
    extern "C"
    {
    static JNIEnv* getJNIEnv(void)
    {
    
        JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
        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().
    static jclass getClassID(JNIEnv *pEnv)
    {
        jclass ret = pEnv->FindClass(CLASS_NAME);
        if (! ret)
        {
            LOGD("Failed to find class of %s", CLASS_NAME);
        }
    
        return ret;
    }
    static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode)
    {
        jmethodID methodID = 0;
        JNIEnv *pEnv = 0;
        bool bRet = false;
    
        do 
        {
            pEnv = getJNIEnv();
            if (! pEnv)
            {
                break;
            }
    
            jclass classID = getClassID(pEnv);
    
            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(char* value){
        JniMethodInfo methodInfo;
        if (! getStaticMethodInfo(methodInfo, "callback", METHOD_SIGNATURE))
        {            
            return;
        }
    
        jstring stringArg = methodInfo.env->NewStringUTF(value);
        methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg1);
        methodInfo.env->DeleteLocalRef(stringArg);
        methodInfo.env->DeleteLocalRef(methodInfo.classID);
    }
    
    }
    

    CLASS_NAME: / METHOD_SIGNATURE: see it from file *.class

提交回复
热议问题