首页 > 解决方案 > DetachCurrentThread 有时在 NDK 中崩溃

问题描述

我原谅我提出了一个非常模糊的问题,但是,我有一个纯原生 NDK 应用程序,它应该在沉浸式模式(即全屏)下执行。

当应用程序通过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从主线程执行。

标签: androidandroid-ndkjava-native-interfaceandroid-fullscreen

解决方案


View.setSystemUiVisibility() 只能从主线程调用。如果没有看到您的代码,很难判断 DetachCurrentThread() 是否在其中发挥了任何作用。

文档中,ANativeActivity::env 是应用程序主线程的 JNI 上下文。

您应该DetachCurrentThread()在终止附加到 JVM 的本机线程之前调用。

您不应该调用DetachCurrentThread)Java 中的线程,例如 UI 线程。

请注意,您可以AttachCurrentThread()随时在任何线程上调用。它将等效于 Java 线程或附加线程上的 NOP。

这些附加/分离不像括号那样配对。任何数量的附加调用都可以通过单次分离来反转。推荐的做法:

用于pthread_key_create定义将在线程退出之前调用的析构函数,并DetachCurrentThread从那里调用。(使用该键pthread_setspecific将 JNIEnv 存储在 thread-local-storage 中;这样它将作为参数传递到您的析构函数中。)

在他们的git Web repo中查看 WebRTC 如何处理附加/分离。


推荐阅读