2

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...

1 Answer 1

1

I found the solution. Instead of calling dynamic method, I make the Java method as static method and call it from C++ using CallStaticVoidMethod. Code example:

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);
    dataUpdateHandle = env->GetStaticMethodID(dataClassHandle, "dataUpdate", "(I)V");
    return JNI_VERSION_1_6;
}

The native function that calls the Java method:

void sendCount(int totalCount) {

jint jtotalCount = totalCount;
jobject dataObjectHandle = env->NewObject(dataClassHandle, dataUpdateHandle);
if (dataObjectHandle == NULL) LOGI("dataObjectHandle null");
LOGI("init CallVoidMethod");
env->CallStaticVoidMethod(dataClassHandle, dataUpdateHandle, jtotalCount);
}

In Java, I declare the method as static method

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.