简体   繁体   中英

Updating UI from background thread using native code entirely (no JNI)?

I am writing an Android application that does much of a processing in the background thread. The calculations are performed in the native code using C++. I want to update UI with the partial results during calculations.

I am able to do so through JNI, namely set reference to UI object in java and then call a method of this object from native code trough JNI. I am looking for a more efficient solution without any JNI calls in the rendering part (the basic setup and an activation entry point will have to be in java).

Is it possible to change execution thread from background to UI entirely in native code without using JNI (only in the rendering part)?

Thanks for your answers. Much appreciated.

EDIT: I am considering using OpenGL to render calculated content (sort of video frames) in my view. In that case I would probably want to use eglSwapBuffers() method that is available in EGL library from 2.3 onwards. The biggest problem is, I think, how to easily switch from background "calculation" thread to UI "open GL" thread in native code without JNI overhead. What would you recommend? Thanks for your help!

PSEUDOCODE: Here is some pseudocode that helps to illustrate what I want to achieve here. It is more like a threading issue but Android framework comes into play as well.

// background thread
void Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz)
{
    //long calculation
    struct result * res = calculate();

    //want to update ui using opengl on ui thread
    updateGL(res);
}


//want to run it on ui thread as opengl can be run only on ui thread
void updateGL(struct result * res)
{
    //some opengl code with "res"
    someGLcodeWithResult(res);

    //render surface
    eglSwapBuffers();
}

EDIT 2: As the bounty slowly draws to close, one more clarification. There are couple of ways to call the updateGL method above. The most typical one is to use GLSurfaceView in java code. It would require setting a renderer ( setRenderer() ) and then overriding onDrawFrame with some code to call JNI/native layer. This way for every frame being rendered one JNI call gets executed.

I would like to do the rendering a little differently. I want to call updateGL without using java/JNI code at all and use only the native layer (as presented in the excerpt above). The biggest problem for me now is how to run the updateGL on UI thread (required by OpenGL) without the java callback. Is it at all feasible?

I suggest taking a look at the Mozilla Fennec source. There is a minimal Java/JNI shim that allows rendering on Android, but all the work is done via native code (regular ol' Mozilla code)

Great thoughts, but try and understand this thing

  1. You have code in C++ in native
  2. UI in java runs in VM

Now what you are asking is C++ code to interact with UI in Java VM which is another program to communicate. The only way to do it would be some interprocess communication. Having said that, now go figure that out which suits you best. JNI is fast and reliable, since u dont want to go that way, figure out any other IPC that suits you.

Is it possible to change execution thread from background to UI entirely in native code without using JNI?

You cannot modify widgets from native code.

I'm facing the same problem right now. Perhaps this might help:

When you take a look at the STABLE-APIS.html in the latest NDK it says:

> V. Android-9 Stable Native APIs:

All the APIs listed below are available for developing native code that runs on Android > 2.3 system images and above.

The EGL graphics library:

EGL provides a native platform interface to allocate and manage OpenGLES surfaces. For more information about its features, please see:

http://www.khronos.org/egl

In a nutshell, this will allow you to do the following directly from native code:

- List supported EGL configurations
- Allocate and release OpenGLES surfaces
- Swap/Flip surfaces for display  (eglSwapBuffers)

So if you're targeting Android-9 then you could try to use the EGL lib in native code. (Let me know if this works :))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM