Ho un grosso problema quando voglio modificare l'attività della mia applicazione Android con una chiamata JNI dal mio codice C++. L'app utilizza cocos2d-x per il rendering. La situazione concreta è che voglio aprire l'OpenFeint-Dashboard in Java utilizzando questo molto piccola funzione:Modifica attività con chiamata JNI o utilizzo di Openfeint causa App-Crash
void launchOpenFeintDashboard() {
Dashboard.open();
}
Questa funzione viene poi chiamato da C++ con un semplice JNI-Call:
void
OFWrapper::launchDashboard() {
// init openfeint
CCLog("CPP Init OpenFeint Dashboard");
CCDirector::sharedDirector()->pause();
jmethodID javamethod = JNIManager::env()->GetMethodID(JNIManager::mainActivity(), "launchOpenFeintDashboard", "()V");
if (javamethod == 0)
return;
JNIManager::env()->CallVoidMethod(JNIManager::mainActivityObj(), javamethod);
CCLog("CPP Init OpenFeint Dashboard done");
}
l'implementazione JNIManager classe è anche molto semplice e basilare:
#include "JNIManager.h"
#include <cstdlib>
static JNIEnv* sJavaEnvironment = NULL;
static jobject sMainActivityObject = NULL;
static jclass sMainActivity = NULL;
extern "C" {
JNIEXPORT void JNICALL Java_net_plazz_mainzelapp_mainzelapp_sendJavaEnvironment(JNIEnv* env, jobject obj);
};
// this function is called from JAVA at startup to get the env
JNIEXPORT void JNICALL Java_net_plazz_mainzelapp_mainzelapp_sendJavaEnvironment(JNIEnv* env, jobject obj)
{
sJavaEnvironment = env;
sMainActivityObject = obj;
sMainActivity = JNIManager::env()->GetObjectClass(obj);
}
JNIEnv*
JNIManager::env()
{
return sJavaEnvironment;
}
jobject
JNIManager::mainActivityObj()
{
return sMainActivityObject;
}
jclass
JNIManager::mainActivity()
{
return sMainActivity;
}
Dal mio punto di vista, cocos2d-x ha qualche problema quando si cambia la cirical attività con una chiamata JNI, perché ho anche un App-Crash quando si cambia l'attività in qualsiasi attività.
MA, anche quando semplicemente uso OpenFeint per aggiornare un risultato con un JNI chiamata ottengo un App-Crash, simile a quando si cambia l'attività:
void updateAchievementProgress(final String achievementIdStr, final String progressStr) {
Log.v("CALLBACK", "updateAchievementProgress (tid:" + Thread.currentThread().getId() + ")");
float x = Float.valueOf(progressStr).floatValue();
final Achievement a = new Achievement(achievementIdStr);
a.updateProgression(x, new Achievement.UpdateProgressionCB() {
@Override
public void onSuccess(boolean b) {
Log.e("In Achievement", "UpdateProgression");
a.notifyAll();
}
@Override
public void onFailure(String exceptionMessage) {
Log.e("In Achievement", "Unlock failed");
a.notifyAll();
}
});
Log.v("CALLBACK", "updateAchievementProgress done (tid:" + Thread.currentThread().getId() + ")");
}
questo mi porta ad un punto su quello che direbbe, che Android o Cocos2d-x ha qualche problema quando si fa qualcosa in modo asincrono (aggiornamento Achievement) o quando si modifica l'attività in combinazione con l'utilizzo di NDK (io uso NDKr7, ma lo stesso su NDKr5).
Si dovrebbe anche sapere che ho già alcune altre funzioni definite in Java che vengono chiamate con una chiamata JNI e che funzionano correttamente!
Forse ho fatto qualcosa di sbagliato, qualcuno può darmi qualche consiglio su questo o un codice di esempio di lavoro su come modificare l'attività. Forse è un problema con Cocos2d-x.
Grazie.
AFAIK l'indirizzo JNI è valido solo finché la chiamata di funzione è attiva ... Inoltre, non è possibile garantire che l'oggetto sia ancora valido. Fondamentalmente abbiamo bisogno di vedere come finisci nella chiamata launchDashboard. cioè dalla voce iniziale a nativo da java ... – Goz
Perché hai più di un 'attività'? Hai controllato questo tutorial: http://blog.molioapp.com/2011/11/openfeint-and-admob-integrated-with.html – Macarse