Android WebView 已开始在 Android 9 上崩溃

Posted

技术标签:

【中文标题】Android WebView 已开始在 Android 9 上崩溃【英文标题】:Android WebView Has started crashing on Android 9 【发布时间】:2019-10-05 06:38:36 【问题描述】:

您好专家 android 开发人员:

我们有一个安卓应用,我们的基本工作流程如下

    通过电子邮件或短信向用户发送链接 用户点击链接,在 Chrome 或 Android 默认浏览器上打开一个页面,并有一个名为 JOIN 的按钮 用户单击此 JOIN 按钮,我们的应用程序将启动,并在 web 视图中显示一个页面,要求用户输入名字、姓氏和电话/电子邮件,然后用户单击名为 INITIATE 的按钮 我们验证信息 - 如果用户是新用户,我们会创建一条记录,该用户是存在的,我们更新它等等,然后显示一个弹出窗口,通知他的会话将被记录。 只要用户在弹出窗口中单击“确定”,然后控件就会存在 web 视图,并且用户位于原生 android 页面上。

问题 一旦在几周前我们的原生应用程序页面正常启动的 web 视图上点击 OK 按钮,应用程序就会崩溃,我们将返回到 web 视图页面的开头,要求我们输入详细信息。

请注意以下注意事项:

首先,这仅发生在 Android 9 的情况下。我们已经在三星 Galaxy S8 和 S9 上对此进行了测试。而且它不会每次都发生,但它会经常发生,我会说有时甚至 3 次中的 2 次。在最好的时期,它发生了 10 次中有 2 次,但它确实发生了。 此代码在过去 1 年左右已成功运行,我们从未遇到过此问题。它只是在过去 3-4 周内才开始发生。 我们还有一个 ios 应用,没有发现同样的问题。

这是一个可能有帮助的代码 sn-p - 这就是我们加载 webview 的方式。

webview = findViewById(R.id.webview);
    webview.setVisibility(View.VISIBLE);
    final ProgressDialog pd = ProgressDialog.show(ActivtyName.this, "", "Please wait", true);
    webview.setGeolocationEnabled(true);
    webview.setMixedContentAllowed(true);
    webview.getSettings().setjavascriptEnabled(true);
    webview.getSettings().setDomStorageEnabled(true);
    webview.getSettings().setLoadWithOverviewMode(true);

    webview.setWebChromeClient(new WebChromeClient()

=======我们这里重写了很多方法,后面跟着

webview.setWebViewClient(new WebViewClient()

=======我们在这里覆盖方法。

知道会发生什么吗?我们尝试在通过 USB 模式调试时查看日志,但除了 Android 控制台上显示的内容外,我们在日志中看不到太多内容,如下所示:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 0, tid: 0 >>> com.a****d.xyzapp <<<

backtrace:

#00  pc 0000000001b61620  /data/app/com.android.chrome-DpcaMBOCm2oa08upmw1Tug==/base.apk

这里是根据要求提供的更详细的日志:

2019-05-18 11:58:01.694 23217-23217/com.a**d.xyzapp.debug A/chromium: 

[FATAL:crashpad_client_linux.cc(404)] Render process (28925)'s crash wasn't handled by all associated  webviews, triggering application crash.
Fatal signal 5 (SIGTRAP), code 1 (TRAP_BRKPT), fault addr 0x7ab7b9d620 in tid 23217 (atientapp.debug), pid 23217 (atientapp.debug) (edited) 

【问题讨论】:

你可以激活fabric.io/kits/android/crashlytics/install这个API提供实时崩溃,帮助理解问题。 如果显示项目的 crash logcat 可以吗? @IsmaelJunior,我刚刚添加了一些额外的日志。你能看一下吗? @DPrince 我添加了额外的日志。你能帮忙吗? 这不是错误日志,这是致命错误日志,我希望您的应用崩溃时出现实际错误。 【参考方案1】:

在你的情况下,渲染进程正在崩溃,它没有被系统杀死。

如here 所述,如果您覆盖

onRenderProcessGone(WebView view,
            RenderProcessGoneDetail detail)

上面的方法然后detail.didCrash() 将持有true 在你的情况下。在这种情况下,渲染器由于内部错误(例如内存访问冲突)而崩溃。应用程序本身在检测到渲染器崩溃后崩溃。

要处理崩溃并让您的应用继续执行,您应该按照以下步骤操作:-

    销毁当前的 WebView 实例。 指定您的应用程序如何继续执行的业务逻辑。 覆盖 onRenderProcessGone 并返回 true

问题只要在 webview 上点击 OK 按钮,我们的 原生应用页面会正常启动,直到几周前,该应用 崩溃,我们将被带回到 webview 页面的开头 要求我们输入详细信息。

这是因为如果渲染器在加载特定网页时崩溃,尝试再次加载同一页面可能会导致新的 WebView 对象呈现相同的渲染崩溃行为。

查看this link中的代码以获取更多信息。

希望这会有所帮助。

【讨论】:

【参考方案2】:

您使用的是 mopub 广告平台吗?如果是这样,他们的 sdk 就有这个错误。 它通常与正在尝试加载的网页中的错误有关。 从上面的 android 8.0 开始,webview 的工作方式也发生了变化。它现在是基于多进程的,这也使您能够处理这些类型的错误(渲染器消失、内存不足和许多其他错误)。 你应该实现这个覆盖

public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail)

更多详情请联系here

更新: 如果您使用的是 mopub 甚至 webview,Android 9.0 会阻止所有非 https 流量。考虑使用替代方式,例如 mopub 有 implemented here。

【讨论】:

【参考方案3】:

虽然我的设备有 6GB 内存,但它仍然崩溃。 Android 8.0+ 上的 webview 是这样实现的,如果 webview 不可见,它的渲染进程将被拉出内存并销毁以节省内存。使用单行更改此实现。

webView.setRendererPriorityPolicy(WebView.RENDERER_PRIORITY_IMPORTANT, false);

将优先级设置为重要表示操作系统保持渲染进程处于活动状态,“false”表示不“在不可见时放弃内存”。 更多详情请看这里 - https://developer.android.com/guide/webapps/managing-webview#renderer-importance 感谢和愉快的编码。

【讨论】:

感谢您的信息,但似乎这些是默认值,所以这不会做任何事情。您可以通过调用webView.getRendererRequestedPriority();webView.getRendererPriorityWaivedWhenNotVisible(); 来验证这一点。【参考方案4】:

这似乎是一个内存问题,我可以从几个线程中找到。

执行此操作,在您的 webview 片段/活动中覆盖 onLowMemory() 并添加日志。

@Override
public void onLowMemory() 
    Log.d("TAG_MEMORY", "Memory is Low");
    super.onLowMemory();

现在尝试重现崩溃,如果调用了 onLowMemory(),那么这就是根本原因。可能有些 webview 页面内存太大。

【讨论】:

【参考方案5】:

我希望这与我之前遇到的问题相同。 Android 9 在安全方面发生了一些变化。因此,基本上默认情况下,它会阻止所有在应用程序中使用的不安全或 SSL 认证的 url 和域。

默认启用网络 TLS 如果您的应用面向 Android 9 或更高版本,则 isCleartextTrafficPermitted() 方法默认返回 false。如果您的应用需要为特定域启用明文,您必须在应用的网络安全配置中为这些域显式设置 cleartextTrafficPermitted 为 true。

您需要使该域获得 SSL 认证并将此代码添加到清单中

<applicaton ....>
<uses-library
            android:name="org.apache.http.legacy"
            android:required="false" />
</application>

在您的应用程序 build.gradle 文件依赖项块中添加以下代码:

dependencies 
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'

如果您现在不习惯保护您的域,那么您也可以在网络配置中排除该域。详细过程在这个页面中提到了

Security configuration for android

【讨论】:

【参考方案6】:

尝试使用

        android:usesCleartextTraffic="true"

在应用程序标签中 - 在你的 AndroidManifest 中

【讨论】:

您最好详细说明此解决方案。但在我看来,这不是解决这个问题的明显方法。 嗨,我也在我的应用程序中使用 webview 经过研究发现 java.io.IOException: Cleartext HTTP traffic to * is not allowed 将其添加到我的清单解决了我的问题

以上是关于Android WebView 已开始在 Android 9 上崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 React Native 在 Android WebView 中隐藏滚动条

YouTube 视频在 WebView Android 中仅在屏幕旋转时播放音频

当我从 setWebChromeClient 使用时,我无法从 onPageStarted webView 使用 - Android

Android WebView loadData读取两次才能显示的问题

Android WebView加载页面的输入框被软键盘遮挡的问题

已安装 Android SDK,但缺少 adb.exe