I am developing in native and Java code for Android.
I plan to invoke a Java listener based on a C/C++ code. The idea is the C/C++ code call a method that actually invoke the Java Listener.
The C/C++ code is as follow. I can call the Java method using code below: the first code block is initiating the methodid and class inside JNI_OnLoad
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
jclass dataClass = env->FindClass("com/example/crowdlogic/NativeManager");
dataClassHandle = (jclass)env->NewGlobalRef(dataClass);
if (dataClassHandle == NULL) LOGI("dataClassHandle null");
LOGI("init dataUpdateHandle");
dataUpdateHandle = env->GetMethodID(dataClassHandle, "dataUpdate", "(I)V");
if (dataUpdateHandle == NULL) LOGI("dataUpdateHandle null");
return JNI_VERSION_1_6;
}
Next codeblock is actually calling it:
void sendCount(int totalCount) {
jint jtotalCount = totalCount;
jobject dataObjectHandle = env->NewObject(dataClassHandle, dataUpdateHandle);
if (dataObjectHandle == NULL) LOGI("dataObjectHandle null");
env->CallVoidMethod(dataObjectHandle, dataUpdateHandle, jtotalCount);
}
In the Java part, the dataUpdate method is actually called, but never invoke the listener. The listener is null. This is the Java listener class
public class NativeManager {
private static final String TAG = "crowdlogic:native_manager";
// all the listener stuff below
public interface Listener {
public void onDataUpdated(int totalCount);
}
private Listener mListener = null;
public void registerListener (Listener listener) {
mListener = listener;
}
public void dataUpdate(int totalCount) { // call this from JNI in C++ class
// now notify if someone is interested.
Log.i(TAG, "Data update in Java called");
if (mListener != null) {
Log.i(TAG, "mListener not null");
mListener.onDataUpdated(totalCount);
}
else
Log.i(TAG, "mListener null"); // always come to this; the listener is null
}
}
In my main activity, I have instantiated the listener (inside onCreate):
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// start listener for data update
mNativeMgr = new NativeManager();
mNativeMgr.registerListener(this);
mNativeMgr.dataUpdate(0);
...
}
I think this is because in the native part, instead of calling the instantiated Java listener object, I actually create a new one using the
jobject dataObjectHandle = env->NewObject(dataClassHandle, dataUpdateHandle);
inside void sendCount(int totalCount).
My question is, how can I get the instantiated Java object rather than create a new one, in the C/C++ code? Thanks guys, spent last 2 days on this already...