Reputation: 13099
I excuse for asking a quite vague question, but, I have a pure native NDK application which is supposed to execute in Immersive Mode (i.e fullscreen).
The immersive mode JNI snippet is executed when the app is resumed via APP_CMD_RESUME
. This works most of the time, but, every now and then the command activity->vm->DetachCurrentThread()
in my SetImmersiveMode()
snippet crashes with a fatal exception:
FATAL EXCEPTION: Thread-10
Process: com.toppluva.portis.LocalDebug, PID: 5474
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7380)
at android.view.ViewRootImpl.recomputeViewAttributes(ViewRootImpl.java:3478)
at android.view.View.setSystemUiVisibility(View.java:22587)
This really boggles me, mainly because it happens every now and then, how can I detect if I'm executing from this original thread?
Note that according to the documentation APP_CMD_RESUME
executes from main thread.
Upvotes: 4
Views: 1978
Reputation: 57163
View.setSystemUiVisibility() should be called from the main thread only. Without seeing your code, it's hard to tell if DetachCurrentThread() plays any role in this.
documentation, ANativeActivity::env is JNI context for the main thread of the app.
You should call DetachCurrentThread()
before terminating a native thread that you attached to JVM.
You should not call DetachCurrentThread)
on a thread born in Java, e.g. the UI thread.
Note that you may call AttachCurrentThread()
at any time and on any thread. It will be equivalent to NOP on a Java thread or on an attached thread.
These attach/detach are not paired like parentheses. Any number of attach calls is reversed by single detach. The recommended practice:
use
pthread_key_create
to define a destructor function that will be called before the thread exits, and callDetachCurrentThread
from there. (Use that key withpthread_setspecific
to store the JNIEnv in thread-local-storage; that way it'll be passed into your destructor as the argument.)
See how WebRTC handles attach/detach in their git Web repo.
Upvotes: 4