Как сделать правильный вызов с Android на нестатическую функцию в Java? (Cocos2Dx в смеси)
Итак, я разрабатываю небольшой проект с Cocos2Dx, но я пытаюсь добавить функциональность Bluetooth, и это подразумевает вызов нестатического метода, чтобы получить доступ к ассоциации основной активности с Android API. Почти все, что я видел, говорит мне, чтобы я следовал этой процедуре: - Создайте экземпляр основного действия (окружение->NewGlobalRef - это то, что я использую) - Получите метод из действия и выполните его (environment->GetObjectClass)
И вот код. В Java у нас есть следующее (без логических вещей, таких как onCreate, onResume и т. Д.):
public class TSP extends Cocos2dxActivity{
public void CnxAttempt(){
Log.e("TSP_BT","aTTEMPTING!");
}
}
Это оно! На данный момент я хочу показать только сообщение журнала, подтверждающее, что функция выполнена. Теперь самое интересное в C++:
static JNIEnv* getJNIEnv(void){
JNIEnv *env = 0;
// get jni environment
if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK){
CCLog("Failed to get the environment using GetEnv()");
}
if (gJavaVM->AttachCurrentThread(&env, 0) < 0){
CCLog("Failed to get the environment using AttachCurrentThread()");
}
return env;
}
typedef struct JniMethodInfo_{
JNIEnv * env; // The environment
jclass classID; // classID
jmethodID methodID; // methodID
} JniMethodInfo; // Struct that stores most of the important information to relate to Java code
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode){
jmethodID methodID = 0;
JNIEnv *pEnv = 0;
jobject methodObject = NULL;
bool bRet = false;
do {
pEnv = getJNIEnv();
if (! pEnv){
CCLog("getMethodInfo -- pEnv false");
break;
}
jclass localRef = pEnv->FindClass("org/cocos2dx/tsp/TSP");
if (localRef == NULL) {
CCLog("getMethodInfo -- localRefCls false");
break; // exception thrown
}
gCallbackObject = pEnv->NewGlobalRef(localRef);
if (gCallbackObject == NULL){
CCLog("getMethodInfo -- CallbackOBJ false");
break;
}
jclass classID = pEnv->GetObjectClass(methodObject);
if (!classID){
CCLog("getMethodInfo -- classID false");
break;
}
methodID = pEnv->GetMethodID(classID, methodName, paramCode);
if (!methodID){
CCLog("getMethodInfo -- methodID false");
break;
}
methodinfo.classID = classID;
methodinfo.env = pEnv;
methodinfo.methodID = methodID;
CCLog("getMethodInfo -- methodinfo created");
bRet = true;
} while(0);
return bRet;
}
void CnxAttempt(){
JniMethodInfo methodInfo; // Creating a JniMethodInfo object to store all the data
if (! getMethodInfo(methodInfo, "CnxAttempt", "()V")){
CCLog("getMethodInfo is FALSE :(");
return;
}
methodInfo.env->CallVoidMethod(methodObject,methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
И это все! При вызове CnxAttempt на C++ он идет BOOM, потому что он не распознает метод в классе Java и не может получить к нему... Кто-нибудь может мне помочь? Если что-то не понятно, пожалуйста, дайте мне знать. Большое спасибо заранее!!
1 ответ
Создание новой глобальной ссылки не создает новый объект. Разница между локальными и глобальными ссылками (из документов):
Локальные ссылки действительны в течение всего времени вызова нативного метода и автоматически освобождаются после возврата нативного метода. Глобальные ссылки остаются действительными до тех пор, пока они не будут явно освобождены.
Если вы хотите вызвать нестатический метод к объекту, вам нужно либо передать объект нативному методу (если он существует - разве основная деятельность уже не существует?), Создайте новый, используя функции NewObject*, или вызывая какой-то фабричный метод.
Затем получите объект класса объекта, получите methodID и затем вызовите метод.