#if defined(JUDGE_OS_ANDROID) #include "JNIApiBridge.h" JNIApiBridge::JNIApiBridge() { } JNIApiBridge::~JNIApiBridge() { bool need = false; JNIEnv* env = ifNeedAttachCurrentThread(need); if(env != NULL) { methodDestory(env, m_cbLog); methodDestory(env, m_cbReal); methodDestory(env, m_cbPerform); methodDestory(env, m_cbMap); } ifNeedDetachCurrentThread(need); } jint JNIApiBridge::JNI_OnLoad(JavaVM* jvm, void* reserved) { m_jvm = jvm; return JNI_OK; } void JNIApiBridge::JNI_OnUnload(JavaVM* jvm, void* reserved) { if(m_jvm) { m_jvm->DestroyJavaVM(); } } //JNI_JUDGE_FUN_IMPL(jstring, examJudgeVersion, (JNIEnv* env, jobject thiz)) jstring JNI_JUDGE_FUN_IMPL(examJudgeVersion)(JNIEnv* env, jobject thiz) { logdebug("call JNI_examJudgeVersion"); const char* version = ExamService::examJudgeVersion(); return env->NewStringUTF(nullptr != version ? version : ""); } jint JNI_JUDGE_FUN_IMPL(examJudgeSetLogCallback)(JNIEnv* env, jobject thiz, jint level) { logdebug("call JNI_examJudgeSetLogCallback"); ExamService::examJudgeSetLogCallback(level, NULL); __DELETE__(m_cbLog); //防止重复注册要销毁 m_cbLog = methodCreate(env, thiz, JNI_FUN(examJudgeCallbackLog)); ErrorCode code = m_cbLog != NULL ? codeSuccess : errorJNISetCallback; return (jint)QE(code); } jstring JNI_JUDGE_FUN_IMPL(examJudgeErrorInfo)(JNIEnv* env, jobject thiz, jint errorCode) { logdebug("call JNI_examJudgeErrorInfo"); const char* errinfo = ExamService::examJudgeErrorInfo(errorCode); return env->NewStringUTF(nullptr != errinfo ? errinfo : ""); } jint JNI_JUDGE_FUN_IMPL(examJudgeInit)(JNIEnv* env, jobject thiz, jstring data, jint len) { logdebug("call JNI_examJudgeInit"); //释放模式 //0 复制回内容并释放缓冲区 //JNI_COMMIT 复制回内容但不释放缓冲区 //JNI_ABORT 释放缓冲区但不复制回变化 //jint version = env->GetVersion(); const char* buf = env->GetStringUTFChars(data, NULL); jsize size = env->GetStringUTFLength(data); TASSERT(buf != nullptr && size == len, ""); int code = ExamService::examJudgeInit(buf, len); env->ReleaseStringUTFChars(data, buf); return (jint)QE((ErrorCode)code); } jint JNI_JUDGE_FUN_IMPL(examJudgeDestroy)(JNIEnv* env, jobject thiz) { logdebug("call JNI_examJudgeDestroy"); int code = ExamService::examJudgeDestroy(); return (jint)QE((ErrorCode)code); } jint JNI_JUDGE_FUN_IMPL(examJudgeBeginExam)(JNIEnv* env, jobject thiz, jstring data, jint len) { logdebug("call JNI_examJudgeBeginExam"); const char* buf = env->GetStringUTFChars(data, NULL); jsize size = env->GetStringUTFLength(data); TASSERT(buf != nullptr && size == len, ""); int code = ExamService::examJudgeBeginExam(buf, len); env->ReleaseStringUTFChars(data, buf); return (jint)QE((ErrorCode)code); } jint JNI_JUDGE_FUN_IMPL(examJudgeEndExam)(JNIEnv *env, jobject thiz) { logdebug("call JNI_examJudgeEndExam"); int code = ExamService::examJudgeEndExam(); return (jint)QE((ErrorCode)code); } jint JNI_JUDGE_FUN_IMPL(examJudgeRealExam)(JNIEnv* env, jobject thiz, jstring data, jint len) { logdebug("call JNI_examJudgeBeginExam"); const char* buf = env->GetStringUTFChars(data, NULL); jsize size = env->GetStringUTFLength(data); TASSERT(buf != nullptr && size == len, ""); int code = ExamService::examJudgeRealExam(buf, len); env->ReleaseStringUTFChars(data, buf); return (jint)QE((ErrorCode)code); } jint JNI_JUDGE_FUN_IMPL(examJudgeSetRealExamCallback)(JNIEnv* env, jobject thiz) { logdebug("call JNI_examJudgeSetRealExamCallback"); __DELETE__(m_cbReal); //防止重复注册要销毁 m_cbReal = methodCreate(env, thiz, JNI_FUN(examJudgeCallbackRealExam)); ErrorCode code = m_cbReal != NULL ? codeSuccess : errorJNISetCallback; return (jint)QE(code); } jint JNI_JUDGE_FUN_IMPL(examJudgeSetPerformCallback)(JNIEnv* env, jobject thiz) { logdebug("call JNI_examJudgeSetPerformCallback"); __DELETE__(m_cbPerform); //防止重复注册要销毁 m_cbPerform = methodCreate(env, thiz, JNI_FUN(examJudgeCallbackPerform)); ErrorCode code = m_cbPerform != NULL ? codeSuccess : errorJNISetCallback; return (jint)QE(code); } jint JNI_JUDGE_FUN_IMPL(examJudgeArtificialMark)(JNIEnv* env, jobject thiz, jint itemno, jstring serial, jint type) { logdebug("call JNI_examJudgeArtificialMark"); const char* markSerial = env->GetStringUTFChars(serial, NULL); //jsize size = env->GetStringUTFLength(data); //TASSERT(buf != nullptr && size == len, ""); int code = ExamService::examJudgeArtificialMark(itemno, markSerial, type); env->ReleaseStringUTFChars(serial, markSerial); return (jint)QE((ErrorCode)code); } jint JNI_JUDGE_FUN_IMPL(examJudgeArtificialItem)(JNIEnv* env, jobject thiz, jint itemno, jint type) { logdebug("call JNI_examJudgeArtificialItem"); int code = ExamService::examJudgeArtificialItem(itemno, type); return (jint)QE((ErrorCode)code); } jint JNI_JUDGE_FUN_IMPL(examJudgeSoundEnd)(JNIEnv* env, jobject thiz, jint itemno, jstring code, jint type) { logdebug("call JNI_examJudgeSoundEnd"); const char* soundCode = env->GetStringUTFChars(code, NULL); //jsize size = env->GetStringUTFLength(data); //TASSERT(buf != nullptr && size == len, ""); int errCode = ExamService::examJudgeSoundEnd(itemno, soundCode, type); env->ReleaseStringUTFChars(code, soundCode); return (jint)QE((ErrorCode)errCode); } jstring JNI_JUDGE_FUN_IMPL(examJudgeTrackFile)(JNIEnv* env, jobject thiz) { logdebug("call JNI_examJudgeTrackFile"); const char* filename = ExamService::examJudgeTrackFile(); return env->NewStringUTF(nullptr != filename ? filename : ""); } jint JNI_JUDGE_FUN_IMPL(examJudgeMapSetParam)(JNIEnv* env, jobject thiz, jint width, jint height) { logdebug("call JNI_examJudgeMapSetParam"); int code = ExamService::examJudgeMapSetParam(width, height); return (jint)QE((ErrorCode)code); } jint JNI_JUDGE_FUN_IMPL(examJudgeMapSetScaling)(JNIEnv* env, jobject thiz, jint scaling) { logdebug("call JNI_examJudgeMapSetScaling"); int code = ExamService::examJudgeMapSetScaling(scaling); return (jint)QE((ErrorCode)code); } jint JNI_JUDGE_FUN_IMPL(examJudgeMapSetDrawing)(JNIEnv* env, jobject thiz, jboolean drawing) { logdebug("call JNI_examJudgeMapSetScaling"); int code = ExamService::examJudgeMapSetDrawing((bool)drawing); return (jint)QE((ErrorCode)code); } jbyteArray JNI_JUDGE_FUN_IMPL(examJudgeMapImage)(JNIEnv* env, jobject thiz) { logdebug("call JNI_examJudgeMapSetDrawing"); const char* data = ExamService::examJudgeMapImage(); int size = ExamService::examJudgeMapSize(); jbyteArray jbytes = env->NewByteArray(size); env->SetByteArrayRegion(jbytes, 0, size, (jbyte*)data);//赋值到jbyteArray // 删除局部引用 //env->DeleteLocalRef(jbytes); //???有问题这里怎么释放? 这里应该不需要 return jbytes; } jint JNI_JUDGE_FUN_IMPL(examJudgeMapImageSetCallback)(JNIEnv* env, jobject thiz) { logdebug("call JNI_examJudgeMapImageSetCallback"); __DELETE__(m_cbMap); //防止重复注册要销毁 m_cbMap = methodCreate(env, thiz, JNI_FUN(examJudgeCallbackMapImage)); ErrorCode code = m_cbMap != NULL ? codeSuccess : errorJNISetCallback; return (jint)QE(code); } jdouble JNI_JUDGE_FUN_IMPL(examCalcGpsDistance)(JNIEnv* env, jobject thiz, jdouble jd1, jdouble wd1, jdouble jd2, jdouble wd2, jdouble h) { logdebug("call JNI_examCalcGpsDistance"); double distance = ExamService::examCalcGpsDistance(jd1, wd1, jd2, wd2, h); return (jdouble)distance; } void JNIApiBridge::examJudgeCallbackLogToCaller(int level, const char* info, int len) { if(NULL == m_cbLog || level < LOG_LV_CLOSE || level > LOG_LV_ALL || NULL == info || len <= 0) { return; } JNI_JUDGE_CALLBACK_ENTER jstring jstr = env->NewStringUTF(info); //len = env->GetStringLength(jstr); callMethodA(env, m_cbLog, jint(level), jstr, jint(len)); env->DeleteLocalRef(jstr); JNI_JUDGE_CALLBACK_LEAVE } void JNIApiBridge::examJudgeCallbackRealExamToCaller(const char* data, int len) { if(NULL == m_cbReal || NULL == data || len <= 0) { return; } JNI_JUDGE_CALLBACK_ENTER jstring jstr = env->NewStringUTF(data); //len = env->GetStringLength(jstr); callMethodA(env, m_cbReal, jstr, jint(len)); env->DeleteLocalRef(jstr); JNI_JUDGE_CALLBACK_LEAVE } void JNIApiBridge::examJudgeCallbackPerformToCaller(const char* data, int len) { if(NULL == m_cbPerform || NULL == data || len <= 0) { return; } JNI_JUDGE_CALLBACK_ENTER jstring jstr = env->NewStringUTF(data); //len = env->GetStringLength(jstr); callMethodA(env, m_cbPerform, jstr, jint(len)); env->DeleteLocalRef(jstr); JNI_JUDGE_CALLBACK_LEAVE } void JNIApiBridge::examJudgeCallbackMapImageToCaller(const char* data, int len) { if(NULL == m_cbMap || NULL == data || len <= 0) { return; } JNI_JUDGE_CALLBACK_ENTER jbyteArray jbytes = env->NewByteArray(len); env->SetByteArrayRegion(jbytes, 0, len, (jbyte*)data); //赋值到jbyteArray callMethodA(env, m_cbMap, jbytes, jint(len)); env->DeleteLocalRef(jbytes); JNI_JUDGE_CALLBACK_LEAVE } jvalue JNIApiBridge::callMethodA(JNIEnv* env, JNIMethodID* method, ...) { jvalue rv; va_list args; va_start(args, method); rv = callMethodV(env, method, args); va_end(args); return rv; } jvalue JNIApiBridge::callMethodV(JNIEnv* env, JNIMethodID* method, va_list args) { jboolean hasException = false; jboolean* excep = &hasException; jvalue rv = { 0 }; if(NULL == method || !method->valid()) { return rv; } jint ret = env->EnsureLocalCapacity(2); if(JNI_OK != ret) { jclass clazz = env->GetObjectClass(method->object); jmethodID mid = method->method; char retv = method->retv.front(); //获取返回值签名类型首字母 switch (retv) { case 'V': JNI_JUDGE_CALL_METHOD(Void); break; // env->CallVoidMethodV(obj, mid, args); case 'Z': rv.z = JNI_JUDGE_CALL_METHOD(Boolean); break; case 'B': rv.b = JNI_JUDGE_CALL_METHOD(Byte); break; case 'C': rv.c = JNI_JUDGE_CALL_METHOD(Char); break; case 'S': rv.s = JNI_JUDGE_CALL_METHOD(Short); break; case 'I': rv.i = JNI_JUDGE_CALL_METHOD(Int); break; case 'J': rv.j = JNI_JUDGE_CALL_METHOD(Long); break; case 'F': rv.f = JNI_JUDGE_CALL_METHOD(Float); break; case 'D': rv.d = JNI_JUDGE_CALL_METHOD(Double); break; case '[': case 'L': rv.l = JNI_JUDGE_CALL_METHOD(Object); break; default: logerror("call method %s sign %s illegal.", method, method->sign.c_str()); env->FatalError("illegal return sign"); break; } env->DeleteLocalRef(clazz); } if(NULL != excep) { //但是当有挂起的异常时返回JNI_TRUE,在没有挂起的异常的时候返回JNI_FALSE *excep = env->ExceptionCheck(); if(JNI_TRUE == *excep) { jthrowable e = env->ExceptionOccurred(); jint code = env->Throw(e); env->DeleteLocalRef(e); env->ExceptionClear(); logerror("call method %s occurred exception %d.", method, code); env->FatalError("call method occurred exception"); } } return rv; } JNIMethodID* JNIApiBridge::methodCreate(JNIEnv* env, jobject thiz, const char* name) { //jclass clazz = env->FindClass(JNI_JUDGE_CLASS_NAME); JNISignID* sig = JNI_JUDGE_METGOD_SIGN(name); TASSERT_NULL(sig != NULL, ""); jclass clazz = env->GetObjectClass(thiz); jmethodID id = env->GetMethodID(clazz, name, sig->sign.c_str()); env->DeleteLocalRef(clazz); return NEW JNIMethodID(*sig, env->NewGlobalRef(thiz), id); } void JNIApiBridge::methodDestory(JNIEnv* env, JNIMethodID* & method) { if(method->object != NULL) { env->DeleteGlobalRef(method->object); } __DELETE__(method); } JNIEnv* JNIApiBridge::ifNeedAttachCurrentThread(bool& need) { need = false; JNIEnv* env = NULL; jint ret = m_jvm->GetEnv(reinterpret_cast(&env), JNI_JUDGE_VERSION); if(JNI_EDETACHED == ret) { JNI_JUDGE_LOG("JavaVM AttachCurrentThreadIfNeeded"); need = true; ret = m_jvm->AttachCurrentThread(&env, nullptr); if(JNI_OK != ret) { JNI_JUDGE_LOG("JavaVM AttachCurrentThread failed"); } else { JNI_JUDGE_LOG("JavaVM AttachCurrentThread ok"); } } else { JNI_JUDGE_LOG("JavaVM AttachCurrentThreadIfNeeded Not"); } return env; } void JNIApiBridge::ifNeedDetachCurrentThread(bool& need) { if(need) { m_jvm->DetachCurrentThread(); } } #endif // JUDGE_OS_ANDROID