Skip to content Skip to sidebar Skip to footer

Using Ndk From C++ Updating Android Ui

My question is related directly to this post: https://groups.google.com/forum/#!topic/android-ndk/291sBdkITyI Basically, I have an application written in C++ compiled with the NDK

Solution 1:

You are right, you must call mMyTextField.setText() from UI thread. Android Java classes provide multiple ways to do it, e.g. View.post() or Handler.post() or Handler.sendMessage(), or Activity.runOnUiThread(). None of these methods is static, they all need a live this object to work.

There are different approaches to resolve this for your purpose. Probably the minimal change to your code will go as follows:

publicclassExampleextendsActivity {

    privatestaticHandler staticHandler;
    privateTextView currentDownloadField;

    @OverridepublicvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Handler handler = newHandler() {
            @OverridepublicvoidhandleMessage(Message msg) {
                this.currentDownloadField.setText(""+ msg.what);
            }
        }
        staticHandler = handler;
        setContentView(R.layout.main_view);
        currentDownloadField = (TextView)findViewById(R.id.download_field);
    }

    @OverrideprotectedvoidonDestroy() {
        staticHandler = null;
    }

    publicstaticvoidsendMessage(int id) {
        staticHandler.sendEmptyMessage(id); // just the what() is filled with the id
    }
}

In the code above, error checking is skipped for brevity.

Alternatively, you could pass the reference to your activity (or handler, or downloadFiled) to the C library, and instead of calling CallStaticVoidMethod() you would use the object global reference and use CallVoidMethod(env, jactivityObj, mid, message).

PS I just wonder, how you expect you system to work if you send a jbyteArray (in Java, that's byte[]) to a callback method that expects int?

Update The simple code above is subject to Handler Leak, thus if you want to reuse it in production, please include a static inner class wrapper around the Handler.

Solution 2:

When your JNI C/C++ function is called, you have the object whose method is called, and the JNIEnv:

JNIEXPORT void JNICALL Java_com_xxx_Yyy_myfunc(JNIEnv *, jobject);

You can call non-static methods of that object.

If your C++ code does not provide a way to pass an extra void* inside it, just store the stuff into a static variable, and be sure to use it only on the UI thread. Or at least always from the same thread.

PS you can try to add thread-safety via thread-local storage etc. But you do not control the life cycle of threads. You will likely get obscure errors because of unclear reasons. So IMO if you need just two threads, have a structure or array of two pairs of that (JNIEnv*, jobject) stuff.

Post a Comment for "Using Ndk From C++ Updating Android Ui"