Android TV应用WebView场景下,遥控器DPad操作或鼠标移动触发NullPointerException崩溃求助
Android TV应用WebView场景下,遥控器DPad操作或鼠标移动触发NullPointerException崩溃求助
问题描述
我最近在开发基于Kotlin的Android TV应用,用Jetpack Compose嵌入WebView加载网页,网页本身加载完全正常,但一旦按下电视遥控器的DPad导航键或者移动鼠标,应用就会直接崩溃,抛出NullPointerException。卡了好几天没搞定,求各位大佬帮忙分析下!
我的代码
package com.example.tvapp import android.annotation.SuppressLint import android.os.Bundle import android.webkit.WebView import android.webkit.WebViewClient import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.runtime.Composable import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.ui.Modifier class MainActivity : ComponentActivity() { @SuppressLint("SetJavaScriptEnabled") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { WebViewScreen(url = "https://portal.centralstage.io") } } } @Composable fun WebViewScreen(url: String) { AndroidView( factory = { context -> WebView(context).apply { settings.javaScriptEnabled = true webViewClient = WebViewClient() loadUrl(url) } }, modifier = Modifier.fillMaxSize() ) }
崩溃日志
FATAL EXCEPTION: main Process: com.example.tvapp, PID: 2811 java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.InputDevice.getVendorId()' on a null object reference at android.view.View.onResolvePointerIcon(View.java:29569) at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2078) at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2092) at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2067) at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2092) at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2067) at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2092) at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2067) at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2092) at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2067) at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2092) at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2067) at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2092) at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2067) at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2092) at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2067) at android.view.ViewRootImpl.updatePointerIcon(ViewRootImpl.java:7116) at android.view.ViewRootImpl.resetPointerIcon(ViewRootImpl.java:7092) at android.view.ViewRootImpl.-$$Nest$mresetPointerIcon(Unknown Source:0) at android.view.ViewRootImpl$ViewRootHandler.handleMessageImpl(ViewRootImpl.java:6046) at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:5862) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
问题分析
从崩溃栈能明确看到,异常出在系统的View.onResolvePointerIcon方法里:当调用InputDevice.getVendorId()时,InputDevice对象是null,直接触发了空指针。这是Android TV平台上Compose和WebView交互的一个兼容性bug——处理遥控器DPad或鼠标输入时,系统尝试解析指针图标,但输入设备对象没被正确初始化或传递,最终导致崩溃。
解决方案
最直接有效的办法是自定义WebView子类,重写onResolvePointerIcon方法,捕获并处理空指针异常,绕过系统层面的崩溃:
步骤1:创建自定义TVWebView类
import android.content.Context import android.view.MotionEvent import android.view.PointerIcon import android.webkit.WebView class TVWebView(context: Context) : WebView(context) { override fun onResolvePointerIcon(event: MotionEvent?, pointerIndex: Int): PointerIcon? { return try { // 正常情况调用父类方法处理 super.onResolvePointerIcon(event, pointerIndex) } catch (e: NullPointerException) { // 捕获空指针,返回默认指针图标避免崩溃 PointerIcon.getSystemIcon(context, PointerIcon.TYPE_DEFAULT) } } }
步骤2:在Composable中替换为自定义WebView
修改WebViewScreen里的WebView创建逻辑,用我们自定义的TVWebView替代原生WebView:
@Composable fun WebViewScreen(url: String) { AndroidView( factory = { context -> TVWebView(context).apply { settings.javaScriptEnabled = true webViewClient = WebViewClient() loadUrl(url) } }, modifier = Modifier.fillMaxSize() ) }
可选补充优化
如果还想更稳妥,可以在WebView初始化时直接设置默认指针图标,提前避免系统触发异常解析:
TVWebView(context).apply { // 其他原有设置... pointerIcon = PointerIcon.getSystemIcon(context, PointerIcon.TYPE_DEFAULT) }
验证效果
替换完成后重新运行应用,测试遥控器DPad导航和鼠标移动操作,应该不会再出现空指针崩溃了。这个方案通过在WebView层拦截异常,绕过了系统层面的输入设备空指针问题,是目前解决该兼容性bug的常用手段。
内容来源于stack exchange
相关产品推荐
相关产品推荐

