You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebView中通过JavaScript设置FLAG_KEEP_SCREEN_ON报错的解决方法

问题

我希望在WebView内通过JavaScript启用或禁用screen_on(屏幕常亮)功能,尝试了以下代码:

@JavascriptInterface
fun setScreenOn(screenOn: Boolean) {
    val window = m_Activity.window
    if (screenOn) {
        Log.d("screen", "addFlag")
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    } else {
        Log.d("screen", "clearFlag")
        window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }
}

但运行时抛出异常:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. Expected: main Calling: JavaBridge
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:11023)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:2473)
at android.view.View.requestLayout(View.java:28020)
at android.view.View.setLayoutParams(View.java:20530)
at android.view.WindowManagerGlobal.updateViewLayout(WindowManagerGlobal.java:464)
at android.view.WindowManagerImpl.updateViewLayout(WindowManagerImpl.java:165)
at android.app.Activity.onWindowAttributesChanged(Activity.java:4364)
at android.view.Window.dispatchWindowAttributesChanged(Window.java:1323)
at com.android.internal.policy.PhoneWindow.dispatchWindowAttributesChanged(PhoneWindow.java:3193)
at android.view.Window.setFlags(Window.java:1309)
at android.view.Window.clearFlags(Window.java:1283)

异常提示“Only the original thread that created a view hierarchy can touch its views.”,请问是否无法通过JavaScript修改FLAG_KEEP_SCREEN_ON?或有什么可行的解决办法?

解答

不是不能通过JavaScript修改FLAG_KEEP_SCREEN_ON,问题核心是线程调用错误:

WebView的@JavascriptInterface方法默认在JavaBridge线程执行,而Android规定所有操作View层级的代码必须在**主线程(UI线程)**运行,这就是触发CalledFromWrongThreadException的原因。

解决办法1:切换到主线程执行窗口标志位修改

利用Activity的runOnUiThread方法,把修改Window标志位的逻辑包裹在主线程任务中:

@JavascriptInterface
fun setScreenOn(screenOn: Boolean) {
    m_Activity.runOnUiThread {
        val window = m_Activity.window
        if (screenOn) {
            Log.d("screen", "addFlag")
            window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        } else {
            Log.d("screen", "clearFlag")
            window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        }
    }
}

解决办法2:通过View的keepScreenOn属性控制

在布局中添加一个不可见的View,通过动态修改它的keepScreenOn属性实现屏幕常亮控制,效果和修改Window标志位一致,代码更简洁:

<!-- 在Activity布局中添加一个隐藏的View -->
<View
    android:id="@+id/keep_screen_trigger"
    android:layout_width="0dp"
    android:layout_height="0dp" />
private val keepScreenTrigger: View = m_Activity.findViewById(R.id.keep_screen_trigger)

@JavascriptInterface
fun setScreenOn(screenOn: Boolean) {
    m_Activity.runOnUiThread {
        keepScreenTrigger.keepScreenOn = screenOn
        Log.d("screen", if (screenOn) "开启屏幕常亮" else "关闭屏幕常亮")
    }
}

内容的提问来源于stack exchange,提问作者Lorenz Meyer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:53:15