Files
LayaNative2.0/Conch/source/conch/CToJavaBridge.cpp
T
2020-11-11 16:17:13 +08:00

1187 lines
34 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
@file CToJavaBridge.cpp
@brief
@author James
@version 1.0
@date 2016_5_19
*/
#include "CToJavaBridge.h"
#include <android/log.h>
#include "util/Log.h"
#include <malloc.h>
#include <imageLib/JCImageRW.h>
#include "fontMgr/JCFontInfo.h"
CToJavaBridge* g_pCToJava=NULL;
std::string CToJavaBridge::JavaClass="layaair/game/browser/ExportJavaFunction";
const char* s_javaClasses[] =
{
"layaair/game/browser/LayaVideoPlayer",
};
const int s_javaClassesSize = 1;
void OnCleanTLS(void* p_dt){
CToJavaBridge::ThreadJNIData* pData = (CToJavaBridge::ThreadJNIData*)p_dt;
pData->pJVM->DetachCurrentThread();
pData->pJVM=0;
pData->pThreadJNI=0;
delete pData;
}
CToJavaBridge* CToJavaBridge::GetInstance(){
if(g_pCToJava==NULL)
g_pCToJava=new CToJavaBridge();
return g_pCToJava;
}
void CToJavaBridge::DelInstance(){
if(g_pCToJava!=NULL)
delete g_pCToJava;
g_pCToJava=NULL;
LOGE("delete CToJavaBridge");
}
CToJavaBridge::CToJavaBridge(){
m_pJVM = 0;
m_pDefJNIEnv = 0;
m_jMethodID = NULL;
m_jMethodIDRefection = NULL;
m_jNativeMethodStrId = NULL;
m_jNativeMethodStrId1 = NULL;
m_jNativeMethodStrId2 = NULL;
m_jClass = NULL;
m_jIntegerClass = NULL;
pthread_key_create (&(m_kThreadkeyJNI), OnCleanTLS);
}
CToJavaBridge::~CToJavaBridge(){
//m_StaticMethods.clear();
}
bool paserParamDesc( const char* p_sDesc,std::vector<int>& p_nParamNum,int& p_nReturnType )
{
if( p_sDesc == NULL )return false;
int nParamNum = 0;
char* sDesc = (char*)p_sDesc;
int nLen = strlen( sDesc );
if( sDesc[0] != '(' )
{
LOGE("=======paserParamDesc格式错误");
return false;
}
bool bPaserReturn = false;
int i = 1;
while( i < nLen )
{
if( sDesc[i] == ')' )
{
i++;
break;
}
else
{
if( sDesc[i] == 'Z' )
{
p_nParamNum.push_back( PT_bool );
}
else if( sDesc[i] == 'B' )
{
p_nParamNum.push_back( PT_byte );
}
else if( sDesc[i] == 'C' )
{
p_nParamNum.push_back( PT_char );
}
else if( sDesc[i] == 'S' )
{
p_nParamNum.push_back( PT_short );
}
else if( sDesc[i] == 'I' )
{
p_nParamNum.push_back( PT_int );
}
else if( sDesc[i] == 'J' )
{
p_nParamNum.push_back( PT_long );
}
else if( sDesc[i] == 'F' )
{
p_nParamNum.push_back( PT_float );
}
else if( sDesc[i] == 'D' )
{
p_nParamNum.push_back( PT_double );
}
else if( sDesc[i] == 'L' )
{
char sTempBuffer[64];
memset( sTempBuffer,0,sizeof(sTempBuffer) );
int n = 0;
while( sDesc[i] != ';' )
{
sTempBuffer[ n ]= sDesc[i];
n++;
i++;
}
if( strcmp( sTempBuffer,"Ljava/lang/String" ) == 0 )
{
p_nParamNum.push_back( PT_String );
}else if(strcmp( sTempBuffer,"Ljava/lang/Object" ) == 0){
p_nParamNum.push_back( PT_object );
}
else
{
LOGE("=======你是想传入Ljava/lang/String吗?格式错误了");
return false;
}
}
else if(sDesc[i] == '[')
{
p_nParamNum.push_back(PT_array);
}
else
{
LOGE("=======paserParamDesc格式暂不支持");
}
}
i++;
}
//处理返回值的
while( i < nLen )
{
if( sDesc[i] == '[' )
{
p_nReturnType = JRT_object;
break;
}
else if( sDesc[i] == 'I' )
{
p_nReturnType = JRT_Int;
break;
}
else if( sDesc[i] == 'L' )
{
char sTempBuffer[64];
memset( sTempBuffer,0,sizeof(sTempBuffer) );
int n = 0;
while( sDesc[i] != ';' )
{
sTempBuffer[ n ]= sDesc[i];
n++;
i++;
}
if( strcmp( sTempBuffer,"Ljava/lang/String" ) == 0 )
{
p_nReturnType = JRT_string;
break;
}
else
{
LOGE("=======你是想传入Ljava/lang/String吗?格式错误了");
return false;
}
}
else if( sDesc[i] == 'V' )
{
p_nReturnType = JRT_void;
break;
}
else if( sDesc[i] == 'F' ){
p_nReturnType = JRT_Float;
break;
}
else
{
LOGE("=======paserParamDesc格式暂不支持");
}
i++;
}
return true;
}
//内部不会保存这些字符串的指针
jmethodID CToJavaBridge::addStaticMethod( JNIEnv* p_Env, const char* p_sCls){
LOGE("=======================addStaticMethod=========zz%x",(long)p_Env);
//初始化
CToJavaBridge::JavaClass = p_sCls;
if( m_pJVM==0){
p_Env->GetJavaVM(&m_pJVM);
m_pDefJNIEnv = p_Env;
// 初始化Java的Class
for(int i = 0; i < s_javaClassesSize; i++)
{
jclass classTemp = p_Env->FindClass(s_javaClasses[i]);
if (!classTemp)
{
LOGI("[Debug][JNI]find class %s failed", s_javaClasses[i]);
continue;
}
jclass savedClass = (jclass)p_Env->NewGlobalRef(classTemp);
m_classMap.insert(std::make_pair(s_javaClasses[i], savedClass));
}
}
if (m_jMethodID == NULL)
{
jclass tmp = p_Env->FindClass(CToJavaBridge::JavaClass.c_str());
LOGI("[########] %s", CToJavaBridge::JavaClass.c_str());
m_jClass =(jclass)p_Env->NewGlobalRef(tmp);
m_jMethodID = p_Env->GetStaticMethodID(m_jClass, "callMethod", "(IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
m_jMethodIDRefection = p_Env->GetStaticMethodID(m_jClass, "callMethodRefection", "(IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
m_jNativeMethodStrId = p_Env->GetStaticMethodID(m_jClass, "callMethod", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
m_jNativeMethodStrId1 = p_Env->GetStaticMethodID(m_jClass, "createTextBitmap", "(Ljava/lang/String;Ljava/lang/String;IIIF)[Ljava/lang/Object;");
tmp = p_Env->FindClass("java/lang/Integer");
m_jIntegerClass = (jclass)p_Env->NewGlobalRef(tmp);
m_jNativeMethodStrId2 = p_Env->GetStaticMethodID(m_jClass, "measureText", "(Ljava/lang/String;Ljava/lang/String;I)[Ljava/lang/Object;");
}
//TODO 传过来的可能是 laya.game.browser.xx, 这里需要转换成 laya/game/browser/xx
/*jmethodID methodid=NULL;
try{
jclass javacls = p_Env->FindClass(p_sCls);
jclass cls = reinterpret_cast<jclass>(p_Env->NewGlobalRef(javacls)); //TODO 引用问题,每添加一个函数就加一次,每删除 一个就减一次
methodid = p_Env->GetStaticMethodID( cls, p_sMethod, p_sDesc);
JavaMethodMap::iterator it = m_StaticMethods.find( p_nKey );
if( it!=m_StaticMethods.end())
{
LOGE("注意:已经存在这个函数的定义了 %d,对应的java函数是 %s", p_nKey, p_sMethod);
//删除对某个java类的引用
p_Env->DeleteGlobalRef((*it).second.cls);
}
JavaMethod method(cls, methodid);
paserParamDesc( p_sDesc,method.paramInfo,method.retureValueType );
m_StaticMethods[p_nKey]=method;
}catch(...){
LOGE("addStaticMethod 失败,可能是函数名称或者参数写错了,请检查一下。\ncls=%s,method=%s", p_sCls, p_sMethod);
}*/
return NULL;
}
CToJavaBridge::ThreadJNIData* CToJavaBridge::checkThreadJNI(){
if( m_pJVM == NULL ) return 0;
void* pdata = pthread_getspecific(m_kThreadkeyJNI);
//如果没有set,则会返回0
if( !pdata ){
ThreadJNIData* pThreadData = new ThreadJNIData();
pThreadData->pJVM = m_pJVM;
m_pJVM->AttachCurrentThread(&(pThreadData->pThreadJNI),0);
if( pThreadData->pThreadJNI == 0 )
return 0;
//设置线程退出的时候的回调
pthread_setspecific( m_kThreadkeyJNI, pThreadData );
return pThreadData;
}
return (ThreadJNIData*)pdata;
}
/*
返回的指针是重新分配内存的。
*/
int* CToJavaBridge::getJavaIntArray(JNIEnv* p_pJNI, jobject p_obj){
jarray javaarr = (jarray)p_obj;
if( javaarr==0 || p_pJNI == NULL )
return 0;
int len = p_pJNI->GetArrayLength(javaarr);
jintArray * arr = reinterpret_cast<jintArray*>(&p_obj);
int* pIntBuff = p_pJNI->GetIntArrayElements(*arr, 0);
int* pRet = new int[len];
if( pRet )
memcpy(pRet, pIntBuff, len*sizeof(int));
else
{}
//释放
p_pJNI->ReleaseIntArrayElements(*arr, pIntBuff, 0);
return pRet;
}
/*
返回的指针是参数提供的
*/
int* CToJavaBridge::getJavaIntArray(JNIEnv* p_pJNI, jobject p_obj , char* p_pBuff, int& p_nByteLen){
jarray javaarr = (jarray)p_obj;
if( javaarr==0 || p_pJNI == NULL )
return 0;
int len = p_pJNI->GetArrayLength(javaarr);
if(len*sizeof(int)>p_nByteLen)//提供的内存不足
return NULL;
jintArray * arr = reinterpret_cast<jintArray*>(&p_obj);
int* pIntBuff = p_pJNI->GetIntArrayElements(*arr, 0);
memcpy(p_pBuff, pIntBuff, len*sizeof(int));
//释放
p_pJNI->ReleaseIntArrayElements(*arr, pIntBuff, 0);
p_nByteLen = len*sizeof(int);
return (int*)p_pBuff;
}
std::string CToJavaBridge::getJavaString( JNIEnv* env, jstring jstr )
{
if (jstr == NULL)return "";
char* sBuffer = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0)
{
sBuffer = (char*)malloc(alen + 1);
memcpy(sBuffer, ba, alen);
sBuffer[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
env->DeleteLocalRef (barr);
env->DeleteLocalRef (strencode);
env->DeleteLocalRef (clsstring);
std::string sRetString="";
if( sBuffer )
{
sRetString = sBuffer;
free( sBuffer );
}
return sRetString;
}
void correctUtfBytes(char* bytes)
{
char three = 0;
while (*bytes != '\0') {
unsigned char utf8 = *(bytes++);
three = 0;
// Switch on the high four bits.
switch (utf8 >> 4) {
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
// Bit pattern 0xxx. No need for any extra bytes.
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0f:
/*
* Bit pattern 10xx or 1111, which are illegal start bytes.
* Note: 1111 is valid for normal UTF-8, but not the
* modified UTF-8 used here.
*/
*(bytes - 1) = '*';
break;
case 0x0e:
// Bit pattern 1110, so there are two additional bytes.
utf8 = *(bytes++);
if ((utf8 & 0xc0) != 0x80) {
--bytes;
*(bytes - 1) = '*';
break;
}
three = 1;
// Fall through to take care of the final byte.
case 0x0c:
case 0x0d:
// Bit pattern 110x, so there is one additional byte.
utf8 = *(bytes++);
if ((utf8 & 0xc0) != 0x80) {
--bytes;
if (three)--bytes;
*(bytes - 1) = '*';
}
break;
}
}
}
void correctUtfBytes(char* bytes);
/*
void CToJavaBridge::getResultValue(JNIEnv* p_pJNI, jstring p_sJString, std::string &ret)
{
ret = getJavaString(p_pJNI, p_sJString);
LOGI("JSAndroidEditBoxgetResultValue::get_Value=%s", ret.c_str());
laya::JCJson jcJson;
int msglen = ret.length();
char* ptmpMsg = new char[msglen + 1];
ptmpMsg[msglen] = 0;
memcpy(ptmpMsg, ret.c_str(), msglen);
if (jcJson.paserJson((char*)ptmpMsg)) {
laya::JsonObject* pRoot = (laya::JsonObject*)jcJson.getRoot();
laya::JsonValue* pCmd = (laya::JsonValue*)pRoot->getNode("v");
int jj = 0;
if (pCmd)
{
ret = pCmd->m_sValue;
LOGI("JSAndroidEditBoxgetResultValue::get_Value1=%s", ret.c_str());
replace_all_distinct(ret, "\\/", "/");
LOGI("JSAndroidEditBoxgetResultValue::get_Value2=%s", ret.c_str());
}
else
{
ret = "";
}
}
else
{
ret = "";
}
delete[]ptmpMsg;
}
*/
bool CToJavaBridge::callMethodRefection(int objid,bool isSyn,const char* className, const char* methodName, const char* params, JavaRet& p_Ret)
{
ThreadJNIData* pThreadData = checkThreadJNI();
if (!pThreadData)return false;
JNIEnv* pJNI = pThreadData->pThreadJNI;
jstring jclassName = pJNI->NewStringUTF(className);
jstring jmethodName = pJNI->NewStringUTF(methodName);
jstring jparams = pJNI->NewStringUTF(params);
jstring ret = (jstring)pJNI->CallStaticObjectMethod(m_jClass, m_jMethodIDRefection, objid,isSyn ,jclassName, jmethodName, jparams);
p_Ret.pJNI = pJNI;
p_Ret.retType = JavaRet::RT_String;
p_Ret.strRet = ret;
pJNI->DeleteLocalRef(jclassName);
pJNI->DeleteLocalRef(jmethodName);
pJNI->DeleteLocalRef(jparams);
return true;
}
/** @brief
通用反射函数
* @param[in]objid 对象id 如果是静态函数设为-1
* @param[in]isSyn 是否是同步 c++
* @param[in]className 类名 如com.utils.test 或者 com/utils/test
* @param[in]methodName函数名
* @param[in]params 参数 jsonArray字符串
* @param[in]p_Ret 用来处理返回值
* @return[out]bool 是否成功
*/
bool CToJavaBridge::callMethod(int objid,bool isSyn,const char* className, const char* methodName, const char* params, JavaRet& p_Ret)
{
ThreadJNIData* pThreadData = checkThreadJNI();
if (!pThreadData)return false;
JNIEnv* pJNI = pThreadData->pThreadJNI;
jstring jclassName = pJNI->NewStringUTF(className);
jstring jmethodName = pJNI->NewStringUTF(methodName);
jstring jparams = pJNI->NewStringUTF(params);
jstring ret = (jstring)pJNI->CallStaticObjectMethod(m_jClass, m_jMethodID, objid,isSyn ,jclassName, jmethodName, jparams);
p_Ret.pJNI = pJNI;
p_Ret.retType = JavaRet::RT_String;
p_Ret.strRet = ret;
pJNI->DeleteLocalRef(jclassName);
pJNI->DeleteLocalRef(jmethodName);
pJNI->DeleteLocalRef(jparams);
return true;
}
/** @brief
* C++直接调用
无参函数的调用 java层返回统一都是string 通过p_eReturnType来决定返回的类型
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, JavaRet& p_Ret, JavaRet::RTType p_eReturnType)
{
ThreadJNIData* pThreadData = checkThreadJNI();
if (!pThreadData)return false;
JNIEnv* pJNI = pThreadData->pThreadJNI;
LOGE(">>>>>>>>>>>>>>>>>>>>>>>>>>>>className:%s,methodName%s", className,methodName);
jstring jclassName = pJNI->NewStringUTF(className);
jstring jmethodName = pJNI->NewStringUTF(methodName);
LOGE(">>>>>>>>>>>>before");
jstring retstr = (jstring)pJNI->CallStaticObjectMethod(m_jClass, m_jNativeMethodStrId, jclassName, jmethodName, NULL);
LOGE(">>>>>>>>>>>>after");
p_Ret.pJNI = pJNI;
p_Ret.retType = p_eReturnType;
p_Ret.strRet = retstr;
switch (p_eReturnType) {
case JavaRet::RT_Object:
break;
case JavaRet::RT_String:
break;
case JavaRet::RT_Int:
{
std::string temp = getJavaString(pJNI, retstr);
sscanf(temp.c_str(), "%d", &p_Ret.intRet);
}
break;
case JavaRet::RT_Float:
{
std::string temp = getJavaString(pJNI, retstr);
sscanf(temp.c_str(), "%f", &p_Ret.floatRet);
}
break;
default:
break;
}
pJNI->DeleteLocalRef(jclassName);
pJNI->DeleteLocalRef(jmethodName);
return true;
}
/** @brief
* C++直接调用 参数为int 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName,int n, JavaRet& ret)
{
char buffer[20];
sprintf(buffer, "[%d]", n);
std::string params(buffer);
return callMethod(-1, true, className, methodName, params.c_str(), ret);
}
/** @brief
* C++直接调用 参数为const char*s1, const char*s2 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, const char*s1, const char*s2, JavaRet& ret)
{
std::string param1 = s1;
replace_all_distinct(param1, "\\", "\\\\");
replace_all_distinct(param1, "\"", "\\\"");
std::string param2 = s2;
replace_all_distinct(param2, "\\", "\\\\");
replace_all_distinct(param2, "\"", "\\\"");
std::string result = "[\"" + param1 + "\",\"" + param2 + "\"]";
return callMethod(-1, true, className, methodName, result.c_str(), ret);
}
/** @brief
C++直接调用 参数为const char*s1, const char*s2 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, const char* s1, const char* s2,const char* s3, JavaRet& ret)
{
std::string param1 = s1;
replace_all_distinct(param1, "\\", "\\\\");
replace_all_distinct(param1, "\"", "\\\"");
std::string param2 = s2;
replace_all_distinct(param2, "\\", "\\\\");
replace_all_distinct(param2, "\"", "\\\"");
std::string param3 = s3;
replace_all_distinct(param3, "\\", "\\\\");
replace_all_distinct(param3, "\"", "\\\"");
std::string result = "[\"" + param1 + "\",\"" + param2 + "\",\"" + param3 +"\"]";
return callMethod(-1, true, className, methodName, result.c_str(), ret);
}
/** @brief
* C++直接调用 参数为const char*s1, int n,如playaAudio 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, const char*s, int n, JavaRet& ret)
{
std::string param1 = s;
replace_all_distinct(param1, "\\", "\\\\");
replace_all_distinct(param1, "\"", "\\\"");
char buffer[20];
sprintf(buffer, "%d", n);
std::string param2(buffer);
std::string result = "[\"" + param1 + "\"," + param2 + "]";
return callMethod(-1, true, className, methodName, result.c_str(), ret);
}
/** @brief
* C++直接调用 参数为const char*s1, int n,如playaAudio 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, const char*s, int n, int n1,JavaRet& ret)
{
std::string param1 = s;
replace_all_distinct(param1, "\\", "\\\\");
replace_all_distinct(param1, "\"", "\\\"");
char buffer[20];
sprintf(buffer, "%d,%d", n,n1);
std::string param2(buffer);
std::string result = "[\"" + param1 + "\"," + param2 + "]";
return callMethod(-1, true, className, methodName, result.c_str(), ret);
}
/** @brief
* C++直接调用 参数为int n1, int n2, const char*s1, const char*s2, const char*s3,目前只有setOnceNotify 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, int n1, int n2, const char*s1, const char*s2, const char*s3, JavaRet& ret)
{
char buffer[40];
sprintf(buffer, "%d,%d,", n1,n2);
std::string param12(buffer);
std::string param1 = s1;
replace_all_distinct(param1, "\\", "\\\\");
replace_all_distinct(param1, "\"", "\\\"");
std::string param2 = s2;
replace_all_distinct(param2, "\\", "\\\\");
replace_all_distinct(param2, "\"", "\\\"");
std::string param3 = s3;
replace_all_distinct(param3, "\\", "\\\\");
replace_all_distinct(param3, "\"", "\\\"");
std::string result = "[" + param12 + "\"" + param1 + "\",\"" + param2 + "\",\"" + param3 + "\"]";
return callMethod(-1, true, className, methodName, result.c_str(), ret);
}
/** @brief
* C++直接调用 参数为int n1, int n2,int n3, const char*s1, const char*s2, const char*s3,目前只有setRepeatNotify 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, int n1, int n2, int n3, const char*s1, const char*s2, const char*s3, JavaRet& ret)
{
char buffer[60];
sprintf(buffer, "%d,%d,%d,", n1, n2,n3);
std::string param123(buffer);
std::string param1 = s1;
replace_all_distinct(param1, "\\", "\\\\");
replace_all_distinct(param1, "\"", "\\\"");
std::string param2 = s2;
replace_all_distinct(param2, "\\", "\\\\");
replace_all_distinct(param2, "\"", "\\\"");
std::string param3 = s3;
replace_all_distinct(param3, "\\", "\\\\");
replace_all_distinct(param3, "\"", "\\\"");
std::string result = "[" + param123 + "\"" + param1 + "\",\"" + param2 + "\",\"" + param3 + "\"]";
return callMethod(-1, true, className, methodName, result.c_str(), ret);
}
/** @brief
* C++直接调用 参数为float f,如 setVolume 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, float f, JavaRet& ret)
{
char buffer[40];
sprintf(buffer, "[%f]", f);
std::string params(buffer);
return callMethod(-1, true, className, methodName, params.c_str(), ret);
}
/** @brief
* C++直接调用 参数为float x float y, 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, float x,float y, JavaRet& ret)
{
char buffer[40];
sprintf(buffer, "[%f,%f]",x,y);
std::string params(buffer);
return callMethod(-1, true, className, methodName, params.c_str(), ret);
}
/** @brief
* C++直接调用 参数为bool b,如 showLoadingviw 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, bool b, JavaRet& ret)
{
return callMethod(-1, true, className, methodName, b?"[true]":"[false]", ret);
}
/** @brief
* C++直接调用 参数为int x,int y,如 setEditBoxSize 直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, int x,int y,JavaRet& ret)
{
char buffer[40];
sprintf(buffer, "[%d,%d]",x,y);
std::string params(buffer);
return callMethod(-1, true, className, methodName, params.c_str(), ret);
}
/** @brief
* C++直接调用 参数为int x,int y,int w,int h 如直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, int x, int y,int w,int h,JavaRet& ret)
{
char buffer[64];
sprintf(buffer, "[%d,%d,%d,%d]", x, y,w,h);
std::string params(buffer);
return callMethod(-1, true, className, methodName, params.c_str(), ret);
}
/** @brief
* C++直接调用 参数为char* s,int x,int y,int w,int h,int bKeyCloseView 如直接调用通用callMethod
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName,const char* s, int x, int y,int w,int h,int bKeyCloseView,JavaRet& ret)
{
std::string param1 = s;
replace_all_distinct(param1, "\\", "\\\\");
replace_all_distinct(param1, "\"", "\\\"");
char buffer[64];
sprintf(buffer, "%d,%d,%d,%d,%d", x, y,w,h,bKeyCloseView);
std::string paramInt(buffer);
std::string result = "[\"" + param1 + "\"," + paramInt + "]";
return callMethod(-1, true, className, methodName, result.c_str(), ret);
}
/** @brief
* C++直接调用
参数为一个字符串的调用 java层返回统一都是string 通过p_eReturnType来决定返回的类型
*/
bool CToJavaBridge::callMethod(const char* className, const char* methodName, const char*s, JavaRet& p_Ret, JavaRet::RTType p_eReturnType)
{
ThreadJNIData* pThreadData = checkThreadJNI();
if (!pThreadData)return false;
JNIEnv* pJNI = pThreadData->pThreadJNI;
jstring jclassName = pJNI->NewStringUTF(className);
jstring jmethodName = pJNI->NewStringUTF(methodName);
jstring jparams = pJNI->NewStringUTF(s);
jstring retstr = (jstring)pJNI->CallStaticObjectMethod(m_jClass, m_jNativeMethodStrId, jclassName, jmethodName, jparams);
p_Ret.pJNI = pJNI;
p_Ret.retType = p_eReturnType;
p_Ret.strRet = retstr;
switch (p_eReturnType) {
case JavaRet::RT_Object:
break;
case JavaRet::RT_String:
break;
case JavaRet::RT_Int:
{
std::string temp=getJavaString(pJNI, retstr);
sscanf(temp.c_str(), "%d", &p_Ret.intRet);
}
break;
case JavaRet::RT_Float:
{
std::string temp = getJavaString(pJNI, retstr);
sscanf(temp.c_str(), "%f", &p_Ret.floatRet);
}
break;
default:
break;
}
pJNI->DeleteLocalRef(jclassName);
pJNI->DeleteLocalRef(jmethodName);
pJNI->DeleteLocalRef(jparams);
return true;
/*replace_all_distinct(s, "\\\"", "\\\\\"");
replace_all_distinct(s, "\"", "\\\"");
s = "[\"" + s + "\"]";
callMethod(objid, isSyn, className, methodName, s.c_str(), ret);*/
}
void CToJavaBridge::replace_all_distinct(std::string& str, const std::string& old_value, const std::string& new_value)
{
for (std::string::size_type pos(0); pos != std::string::npos; pos += new_value.length()) {
if ((pos = str.find(old_value, pos)) != std::string::npos)
str.replace(pos, old_value.length(), new_value);
else break;
}
}
bool CToJavaBridge::getTextBitmap(laya::BitmapData* bitmapData, const char*text, laya::JCFontInfo* pFontInfo, int fontColor, int borderSize, int nBorderColor)
{
ThreadJNIData* pThreadData = checkThreadJNI();
if (!pThreadData)return false;
JNIEnv* pJNI = pThreadData->pThreadJNI;
jstring jstrFont = pJNI->NewStringUTF(pFontInfo->m_sFamily);
jstring jstrText = pJNI->NewStringUTF(text);
jobjectArray objectArray = (jobjectArray)pJNI->CallStaticObjectMethod(m_jClass, m_jNativeMethodStrId1, jstrText, jstrFont, pFontInfo->m_nFontSize, fontColor, borderSize, nBorderColor);
if (objectArray == NULL)
{
pJNI->DeleteLocalRef(jstrText);
pJNI->DeleteLocalRef(jstrFont);
return false;
}
int maxSize = bitmapData->m_nWidth * bitmapData->m_nHeight;
jobject objInteger = pJNI->GetObjectArrayElement(objectArray, 0);
jmethodID intValue = pJNI->GetMethodID(m_jIntegerClass, "intValue", "()I");
bitmapData->m_nWidth = (int)pJNI->CallIntMethod( objInteger, intValue);
pJNI->DeleteLocalRef(objInteger);
objInteger = pJNI->GetObjectArrayElement(objectArray, 1);
intValue = pJNI->GetMethodID(m_jIntegerClass, "intValue", "()I");
bitmapData->m_nHeight = (int)pJNI->CallIntMethod(objInteger, intValue);
pJNI->DeleteLocalRef(objInteger);
if (maxSize < bitmapData->m_nWidth * bitmapData->m_nHeight)
{
LOGW("CToJavaBridge::getTextBitmap the buffersize is insufficient.");
return false;
}
jbyteArray newArray = (jbyteArray)pJNI->GetObjectArrayElement( objectArray, 2);
jsize theArrayLen = pJNI->GetArrayLength(newArray);
pJNI->GetByteArrayRegion(newArray, 0, theArrayLen, (jbyte*)bitmapData->m_pImageData);
pJNI->DeleteLocalRef(newArray);
pJNI->DeleteLocalRef(objectArray);
pJNI->DeleteLocalRef(jstrText);
pJNI->DeleteLocalRef(jstrFont);
return true;
}
void CToJavaBridge::measureText(laya::JCFontInfo* pFontInfo, const char* p_sText, int& nResultWidth, int& nResultHeight)
{
ThreadJNIData* pThreadData = checkThreadJNI();
if (!pThreadData)return;
JNIEnv* pJNI = pThreadData->pThreadJNI;
jstring jstrText = pJNI->NewStringUTF(p_sText);
jstring jstrFont = pJNI->NewStringUTF(pFontInfo->m_sFamily);
jobjectArray objectArray = (jobjectArray)pJNI->CallStaticObjectMethod(m_jClass, m_jNativeMethodStrId2, jstrText, jstrFont, (int)pFontInfo->m_nFontSize);
if (objectArray == NULL)
{
pJNI->DeleteLocalRef(jstrText);
pJNI->DeleteLocalRef(jstrFont);
return;
}
jobject objInteger = pJNI->GetObjectArrayElement(objectArray, 0);
jmethodID intValue = pJNI->GetMethodID(m_jIntegerClass, "intValue", "()I");
nResultWidth = (int)pJNI->CallIntMethod(objInteger, intValue);
pJNI->DeleteLocalRef(objInteger);
objInteger = pJNI->GetObjectArrayElement(objectArray, 1);
intValue = pJNI->GetMethodID(m_jIntegerClass, "intValue", "()I");
nResultHeight = (int)pJNI->CallIntMethod(objInteger, intValue);
pJNI->DeleteLocalRef(objInteger);
pJNI->DeleteLocalRef(objectArray);
pJNI->DeleteLocalRef(jstrText);
pJNI->DeleteLocalRef(jstrFont);
return;
}
bool CToJavaBridge::getClassAndMethod(const char* className, const char* methodName, const char* methodSign, JNIEnv** ppEnv, jclass* pClazz, jmethodID* pMethodId)
{
ThreadJNIData* pThreadData = checkThreadJNI();
if (!pThreadData)return false;
*ppEnv = pThreadData->pThreadJNI;
JNIEnv* pEnv = *ppEnv;
jclass thisClass = NULL;
auto it = m_classMap.find(className);
if (it != m_classMap.end())
thisClass = it->second;
if (thisClass == NULL)
{
LOGE("[Debug][???]Get class failed");
return false;
}
//LOGI("[Debug][???]Get class OK %d", thisClass);
*pClazz = thisClass;
jmethodID methodID = pEnv->GetMethodID(thisClass, methodName, methodSign);
if (NULL == methodID)
{
LOGE("[Debug][???]GetMethodID %s failed", methodName);
return false;
}
//LOGI("[Debug][Video]GetMethodID %s OK %d", methodName, methodID);
*pMethodId = methodID;
return true;
}
bool CToJavaBridge::newObject(jobject* obj, const char* className)
{
static const char* s_methodSign = "()V";
//jclass cls = pJNI->FindClass(className);
JNIEnv* pJNI = nullptr;
jclass cls = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, "<init>", s_methodSign, &pJNI, &cls, &methodID);
if (!ok)
return false;
jobject newObj = pJNI->NewObject(cls, methodID);
*obj = pJNI->NewGlobalRef(newObj);
if (*obj == NULL)
{
LOGI("[Debug][???]New object failed");
return false;
}
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::newObject(jobject* obj, const char* className, intptr_t thisObj)
{
static const char* s_methodSign = "(J)V";
//jclass cls = pJNI->FindClass(className);
JNIEnv* pJNI = nullptr;
jclass cls = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, "<init>", s_methodSign, &pJNI, &cls, &methodID);
if (!ok)
return false;
jobject newObj = pJNI->NewObject(cls, methodID, (int64_t)thisObj);
*obj = pJNI->NewGlobalRef(newObj);
if (*obj == NULL)
{
LOGI("[Debug][???]New object failed");
return false;
}
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::disposeObject(jobject& obj, const char* className, const char* methodName)
{
static const char* s_methodSign = "()V";
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
if (!obj)
{
LOGE("[CToJavaBridge::disposeObject] obj is null");
return false;
}
pJNI->CallVoidMethod(obj, methodID);
pJNI->DeleteGlobalRef(obj);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::callObjVoidMethod(jobject& obj, const char* className, const char* methodName)
{
if (obj == NULL)
return false;
static const char* s_methodSign = "()V";
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
pJNI->CallVoidMethod(obj, methodID);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::callObjVoidMethod(jobject& obj, const char* className, const char* methodName, const char* arg)
{
if (obj == NULL)
return false;
static const char* s_methodSign = "(Ljava/lang/String;)V";
//jclass thisClass = m_pDefJNIEnv->GetObjectClass(obj);
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
jstring jArg = pJNI->NewStringUTF(arg);
pJNI->CallVoidMethod(obj, methodID, jArg);
pJNI->DeleteLocalRef(jArg);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::callObjVoidMethod(jobject& obj, const char* className, const char* methodName, int32_t arg)
{
if (obj == NULL)
return false;
static const char* s_methodSign = "(I)V";
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
pJNI->CallVoidMethod(obj, methodID, arg);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::callObjVoidMethod(jobject& obj, const char* className, const char* methodName, int64_t arg)
{
if (obj == NULL)
return false;
static const char* s_methodSign = "(J)V";
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
pJNI->CallVoidMethod(obj, methodID, arg);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::callObjVoidMethod(jobject& obj, const char* className, const char* methodName, bool arg)
{
if (obj == NULL)
return false;
static const char* s_methodSign = "(Z)V";
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
pJNI->CallVoidMethod(obj, methodID, arg);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::callObjVoidMethod(jobject& obj, const char* className, const char* methodName, double arg)
{
if (obj == NULL)
return false;
static const char* s_methodSign = "(D)V";
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
pJNI->CallVoidMethod(obj, methodID, arg);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::callObjRetMethod(jobject& obj, const char* className, const char* methodName, int* ret)
{
if (obj == NULL)
return false;
static const char* s_methodSign = "()I";
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
*ret = (int) pJNI->CallIntMethod(obj, methodID);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::callObjRetMethod(jobject& obj, const char* className, const char* methodName, double* ret)
{
if (obj == NULL)
return false;
static const char* s_methodSign = "()D";
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
*ret = pJNI->CallDoubleMethod(obj, methodID);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
bool CToJavaBridge::callObjRetMethod(jobject& obj, const char* className, const char* methodName, bool* ret)
{
if (obj == NULL)
return false;
static const char* s_methodSign = "()Z";
JNIEnv* pJNI = nullptr;
jclass thisClass = NULL;
jmethodID methodID = NULL;
bool ok = getClassAndMethod(className, methodName, s_methodSign, &pJNI, &thisClass, &methodID);
if (!ok)
return false;
*ret = (bool)pJNI->CallBooleanMethod(obj, methodID);
if (pJNI->ExceptionOccurred()) {
pJNI->ExceptionDescribe();
pJNI->ExceptionClear();
}
return true;
}
//------------------------------------------------------------------------------
//-----------------------------END FILE--------------------------------