Android 覆盖 shouldInterceptRequest 的 WebView 即时崩溃
Android WebView instant crash with shouldInterceptRequest override
我有一些 'fun' 和 Android WebView。
我用它来显示登录屏幕,然后在响应时拦截授权代码。应该很简单...
如果我只覆盖 shouldOverrideUrlLoading 但如果我覆盖(就像 Android Studio 自动完成的那样),我的 WebView 加载和显示绝对正常:
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse {
return super.shouldInterceptRequest(view, request)
}
在没有其他更改的情况下,它会在运行时立即崩溃并出现本机崩溃
A/chromium: [FATAL:jni_android.cc(259)]
其次是
A/libc: Fatal signal 6 (SIGABRT), code -6 (SI_TKILL) in tid 16220 (TaskSchedulerFo), pid 16175 (eports.internal)
奇怪的是,如果我使响应可以为空,WebView 将再次工作。但是,在 shouldInterceptRequest 方法中添加任何其他内容会使它因相同的错误而失败。
所以这有效:
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
return super.shouldInterceptRequest(view, request)
}
但这会因上述崩溃而崩溃:
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
val url = view?.url
return super.shouldInterceptRequest(view, request)
}
这似乎是一个非常奇怪的问题,我不明白为什么添加 val 赋值会有任何不同。
我一直在研究错误,建议添加
webView.destroy()
在 activity/fragments onDestroy/onDestroyView 中,不幸的是这没有帮助。
在设备和模拟器上的行为是相同的,在 Android sdk 22 和 28 上也是一样的。
有人以前见过这样的东西吗?我觉得我可能遗漏了一些明显的东西。
万一它对任何人都有用,我还生成了 Breakpad Microdump,在这个问题中它太大 post。但让我知道它或它的一个子集是否有助于诊断!
我在我的案例中发现了这个问题,所以我想我会 post 在这里为处于类似位置的任何其他人提供它。
本机崩溃是由 WebView 中的 Java 脚本 运行 引起的。
WebView 在后台线程中运行 JavaScript,因此任何触及 UI 线程的东西都会导致它在本机级别失败。给出上面非常无用的崩溃。
val 分配导致崩溃的原因不是 val 的分配,而是调用 if view?.url,它在 UIThread 上。
解决方案?
科特林:
webView?.post{
// Do your UI work here.
}
Java:
webView.post(new Runnable(){
public void run() {
// Do your UI work here.
}
})
并且不要在重写的方法中触及 UI线程!
如果您正在编写 Kotlin 代码来实现 WebViewClient
,您应该查看此答案并检查您的 Kotlin 重写方法签名。
我遇到了同样的运行时异常,发现导致此问题的原因是 Kotlin 编译器未将 Java 方法的 return 类型转换为 Kotlin 方法 return 类型。
Java代码的方法签名:
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
通过覆盖方法自动完成与 Kotlin 互操作:
override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse
缺少 Kotlin 方法 return 类型 ?
。
你所要做的就是将 ?
添加到 WebResourceResponse
,例如
override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse?
我有一些 'fun' 和 Android WebView。
我用它来显示登录屏幕,然后在响应时拦截授权代码。应该很简单...
如果我只覆盖 shouldOverrideUrlLoading 但如果我覆盖(就像 Android Studio 自动完成的那样),我的 WebView 加载和显示绝对正常:
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse {
return super.shouldInterceptRequest(view, request)
}
在没有其他更改的情况下,它会在运行时立即崩溃并出现本机崩溃
A/chromium: [FATAL:jni_android.cc(259)]
其次是
A/libc: Fatal signal 6 (SIGABRT), code -6 (SI_TKILL) in tid 16220 (TaskSchedulerFo), pid 16175 (eports.internal)
奇怪的是,如果我使响应可以为空,WebView 将再次工作。但是,在 shouldInterceptRequest 方法中添加任何其他内容会使它因相同的错误而失败。
所以这有效:
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
return super.shouldInterceptRequest(view, request)
}
但这会因上述崩溃而崩溃:
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
val url = view?.url
return super.shouldInterceptRequest(view, request)
}
这似乎是一个非常奇怪的问题,我不明白为什么添加 val 赋值会有任何不同。
我一直在研究错误,建议添加
webView.destroy()
在 activity/fragments onDestroy/onDestroyView 中,不幸的是这没有帮助。
在设备和模拟器上的行为是相同的,在 Android sdk 22 和 28 上也是一样的。
有人以前见过这样的东西吗?我觉得我可能遗漏了一些明显的东西。
万一它对任何人都有用,我还生成了 Breakpad Microdump,在这个问题中它太大 post。但让我知道它或它的一个子集是否有助于诊断!
我在我的案例中发现了这个问题,所以我想我会 post 在这里为处于类似位置的任何其他人提供它。
本机崩溃是由 WebView 中的 Java 脚本 运行 引起的。
WebView 在后台线程中运行 JavaScript,因此任何触及 UI 线程的东西都会导致它在本机级别失败。给出上面非常无用的崩溃。
val 分配导致崩溃的原因不是 val 的分配,而是调用 if view?.url,它在 UIThread 上。
解决方案?
科特林:
webView?.post{
// Do your UI work here.
}
Java:
webView.post(new Runnable(){
public void run() {
// Do your UI work here.
}
})
并且不要在重写的方法中触及 UI线程!
如果您正在编写 Kotlin 代码来实现 WebViewClient
,您应该查看此答案并检查您的 Kotlin 重写方法签名。
我遇到了同样的运行时异常,发现导致此问题的原因是 Kotlin 编译器未将 Java 方法的 return 类型转换为 Kotlin 方法 return 类型。
Java代码的方法签名:
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
通过覆盖方法自动完成与 Kotlin 互操作:
override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse
缺少 Kotlin 方法 return 类型 ?
。
你所要做的就是将 ?
添加到 WebResourceResponse
,例如
override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse?