subject-two/entry/src/main/cpp/sdk/api/jni/JNIApiBridge.cpp

406 lines
13 KiB
C++
Raw Normal View History

2024-07-11 16:16:43 +08:00
#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);
}
2024-07-31 13:47:40 +08:00
jint JNI_JUDGE_FUN_IMPL(examJudgeArtificialMark)(JNIEnv* env, jobject thiz, jint itemno, jstring serial, jint type)
2024-07-11 16:16:43 +08:00
{
logdebug("call JNI_examJudgeArtificialMark");
const char* markSerial = env->GetStringUTFChars(serial, NULL);
//jsize size = env->GetStringUTFLength(data);
//TASSERT(buf != nullptr && size == len, "");
2024-07-31 13:47:40 +08:00
int code = ExamService::examJudgeArtificialMark(itemno, markSerial, type);
2024-07-11 16:16:43 +08:00
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);
}
2024-08-26 16:07:11 +08:00
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;
}
2024-07-11 16:16:43 +08:00
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<void**>(&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