DetachCurrentThread иногда дает сбой в NDK

Прошу прощения за довольно расплывчатый вопрос, но у меня есть чисто родное приложение NDK, которое должно выполняться в режиме погружения (т. е. в полноэкранном режиме).

Фрагмент JNI иммерсивного режима выполняется, когда приложение возобновляется через APP_CMD_RESUME. Это работает в большинстве случаев, но время от времени команда activity->vm->DetachCurrentThread() в моем фрагменте SetImmersiveMode() падает с фатальным исключением:

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)

Меня это действительно смущает, в основном потому, что это происходит время от времени, как я могу определить, работаю ли я из этого исходного потока?

Обратите внимание, что согласно документации APP_CMD_RESUME выполняется из основного потока.


person Viktor Sehr    schedule 14.09.2018    source источник


Ответы (1)


View.setSystemUiVisibility() следует вызывать только из основного потока. Не видя вашего кода, трудно сказать, играет ли DetachCurrentThread() какую-либо роль в этом.

документации, ANativeActivity::env — это контекст JNI для основного потока приложения.

Вы должны вызвать DetachCurrentThread() перед завершением собственного потока, который вы присоединили к JVM.

Вы не должны вызывать DetachCurrentThread) в потоке, созданном на Java, например. поток пользовательского интерфейса.

Обратите внимание, что вы можете вызывать AttachCurrentThread() в любое время и в любом потоке. Это будет эквивалентно NOP в потоке Java или в присоединенном потоке.

Эти присоединения/отсоединения не являются парными, как круглые скобки. Любое количество вызовов присоединения реверсируется одним отсоединением. рекомендуется:

используйте pthread_key_create, чтобы определить функцию деструктора, которая будет вызываться перед выходом из потока, и оттуда вызовите DetachCurrentThread. (Используйте этот ключ с pthread_setspecific, чтобы сохранить JNIEnv в локальном хранилище потока; таким образом, он будет передан в ваш деструктор в качестве аргумента.)

Посмотрите, как WebRTC обрабатывает присоединение/отсоединение в их Веб-репозиторий git.

person Alex Cohn    schedule 15.09.2018
comment
Спасибо, хм, моя проблема в том, что APP_CMD_RESUME исходит из основного потока в соответствии с документацией:/ (вопрос об обновлении) - person Viktor Sehr; 16.09.2018
comment
Если вы обрабатываете этот обратный вызов в основном потоке, который не является потоком, который вы можете присоединить, как DetachCurrentThread() участвует? - person Alex Cohn; 16.09.2018
comment
Вы имеете в виду, что я вообще не могу запустить jni из основного потока или что я должен использовать android_app-›activity-›env без подключения? (который, кажется, терпит крах) - person Viktor Sehr; 17.09.2018
comment
Согласно документации, ANativeActivity::env является контекстом JNI. для основного потока приложения. Обычно не проблема вызвать AttachCurrentThread() в любое время и в любом потоке. Это будет эквивалентно NOP в потоке Java или в присоединенном потоке. Но вы не можете вызывать DetachCurrentThread) в потоке, созданном на Java, например. поток пользовательского интерфейса. - person Alex Cohn; 17.09.2018
comment
Обратите внимание на обратный вопрос. - person Alex Cohn; 17.09.2018
comment
Спасибо за ваше время, прикрепление в любое время было недостающей частью моего следа мыслей. (Кажется, я решил свою настоящую проблему с иммерсивным перемещением, просто перехватив все исключения в java перед отсоединением). - person Viktor Sehr; 17.09.2018