Cordova - Android 上的 XHR 请求在模拟器中工作,但在手机上不工作

Posted

技术标签:

【中文标题】Cordova - Android 上的 XHR 请求在模拟器中工作,但在手机上不工作【英文标题】:Cordova - XHR Requests on Android work in Emulator, but not on Phones 【发布时间】:2019-12-13 02:56:08 【问题描述】:

所以我有一个已经在应用商店上架了很长一段时间的现有应用,截至 3 天前,我收到了更多支持查询,说我的应用无法连接到我的服务。

现在它终于在我的 android 设备上发生了 - 一切都适用于 ios,并且适用于模拟器上的 Android - 但在现实世界中什么都没有。

我已经尽我所能使用 Cordova 进行逐步调试,它通过了白名单测试。我的第一个 XHR 请求运行良好,但随后的请求总是失败,直到我完全关闭应用程序并重新打开。

我正在使用cordova-plugin-whitelist@1.3.4 - 我也尝试过cordova-plugin-whitelist@1.0.0

我的Content-Security-Policy 看起来像这样

<meta http-equiv="Content-Security-Policy" content="default-src * 'self' gap:; img-src http://*.my-site.com.au https://*.my-site.com.au https://*.my-site.com http://*.my-site.com https://*.googleusercontent.com http://*.googleapis.com  https://google.com https://*.google.com https://*.googleapis.com https://*.gstatic.com 'self' data:; style-src http://*.googleapis.com https://*.googleapis.com 'self' 'unsafe-inline'; script-src 'self' https://*.googleapis.com http://*.googleapis.com http://maps.google.com http://*.gstatic.com https://*.gstatic.com https://maps.google.com 'unsafe-inline' 'unsafe-eval'">

我的 Cordova 配置有

<allow-navigation href="*" />
<allow-navigation href="http://*/*" />
<allow-navigation href="https://*/*" />

我尝试使用&lt;access origin="*" /&gt; 添加/删除/替换上述/每个组合,但没有运气。

我的 XHR 响应总是如下所示

xhr.responseUrl = "http://my-site.com/?d=12343902i49"
xhr.status = 0
xhr.responseText = ""

我已经在 Cordova 插件中逐步调试了 XHR 请求,通过在 Whitelist.java 之外的逐步调试,但一切都恢复正常,它成功地上线了

// If we don't need to special-case the request, let the browser load it.
return null;

函数

WebResourceResponse shouldInterceptRequest(WebView view, String url)

org.apache.cordova.engine.SystemWebViewClient.java

我的 Android 清单有以下内容

<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.location.gps" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECORD_VIDEO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />

我使用的是 Cordova@8.0.0,Cordova 平台 Android@8.0.0

我花了几个小时试图深入挖掘,我在这里错过了什么?任何帮助将不胜感激!

【问题讨论】:

模拟器的操作系统和设备的操作系统是什么? 什么是 XHR 错误日志 【参考方案1】:

我发誓我要跳下去。

&lt;uses-sdk android:minSdkVersion="19" android:targetSdkVersion="26" /&gt;

将 targetSdkVersion 从 28 更改为 26。有效。但这将是一场噩梦。

编辑:问题又回来了,但仅限于三星 Galaxy 平板电脑。我无法在其他任何地方复制这种行为。

Edit2:事情……又好了?

【讨论】:

您还希望有人回答这个问题还是您的问题解决了? 顺便把你的targetSdkVersion设置为29。这是最新的 @GauravMall 很奇怪。这个问题在没有干预的情况下自行解决(第三次),我们只是遇到了三星 Galaxy Tablet S2 和三星 Note 9 的问题,我非常困惑,我只是祈祷它不会再有问题.我们测试的所有其他设备都运行良好。 可能只是设备问题。我建议使用某种测试实验室(如 firebase)来查看它是一般问题还是仅限设备问题。【参考方案2】:

尝试将android:usesCleartextTraffic="true" 添加到AndroidManifest.xml 中的&lt;application&gt; 或使用config.xml 如下所示

<platform name="android">
  <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
      <application android:usesCleartextTraffic="true" />
  </edit-config>
</platform>

android:usesCleartextTraffic 指示应用是否打算使用明文网络流量,例如明文 HTTP。默认 针对 API 级别 27 或更低级别的应用的值为“true”。应用程序 目标 API 级别 28 或更高级别默认为“false”。 More info

明文是任何传输或存储的信息 加密或打算加密。当应用程序与 服务器使用明文网络流量,例如 HTTP,它可以 会增加窃听和篡改内容的风险,这就是为什么在最新的 Android 设备中默认设置为 false

【讨论】:

这对我有用。现在我至少从我登录到控制台的服务器那里得到了响应。【参考方案3】:

如果你降低targetSDK问题就消失了,可能是Nidhin Josehp提到的usesCleartextTraffic。它仅在面向 SDK 28 或更高版本时影响 Android 8 或更高版本的设备。

您可以将其添加到 config.xml

<platform name="android">
  <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
      <application android:usesCleartextTraffic="true" />
  </edit-config>
</platform>

您可能需要将config.xml 中的小部件标签更改为如下所示:

<widget id="com.your.app.id" version="1.0.0"
xmlns="http://www.w3.org/ns/widgets" 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cdv="http://cordova.apache.org/ns/1.0">

(添加的是xmlns:android="http://schemas.android.com/apk/res/android"

【讨论】:

很奇怪,这是问题所在,我正在使用 https,所以我想知道还有什么问题 - 无论如何是的,这确实解决了问题。 很好的修复!花了几个小时挖掘这个。非常感谢。【参考方案4】:

您的问题听起来与Cordova doesn't send origin on request in some Android devices 中讨论的非常相似,这是指由 Chrome 76 中引入的错误引起的与 CORS 相关的问题(基于相同版本的 WebKit 的 WebViews 也受到影响)。 Chrome 76 于 2019 年 8 月开始推出。如果受影响的应用重新启动但随机返回,问题通常会消失。

对应的票是https://bugs.chromium.org/p/chromium/issues/detail?id=991107。根据票证,该问题已在 Chrome 76.0.3809.111 中得到解决,这些天正在推出。

在您的模拟器上,您可能使用的是旧版本的 Chrome,这可能是问题没有出现的原因。如果您比较受影响和未受影响的设备,发现只有运行 Chrome 版本 >= 76.0 和 76.0.3809.111 的设备出现症状,您可能找到了问题的原因。

如果是这种情况,您至少有以下选择:

请稍等,Chrome 的固定版本已经推出(许多受影响的手机可能已经出现这种情况)。 如果您可以控制服务器,您可以将file:// 原点添加到the list of allowed origins 那里,which is what we did。不过,您必须仔细考虑安全隐患。

顺便说一句,重新启动应用程序后,该问题通常会消失,这使得调试变得困难。我们发现,可以通过卸载并重新安装受影响的应用程序来重现它。

【讨论】:

@DoD 您能否找出问题是否仅出现在运行 Chrome 76(或相应的基于 WebKit 的 WebView)的设备上?我添加了有关如何重现问题的信息(通过重新安装应用程序)。顺便说一句,你会发现这个问题的最官方参考可能是bugs.chromium.org/p/chromium/issues/detail?id=991107。 它自己修复了,我真的很困惑。那没有意义。我再也没有收到客户对此的任何投诉。 嗯,这可能是一个很好的迹象,这就是您问题的答案。该问题可能已通过 Chrome 76.0.3809.111、which was released on Aug 9th 解决,随后推出。客户收到新版 Chrome 后,问题就消失了。

以上是关于Cordova - Android 上的 XHR 请求在模拟器中工作,但在手机上不工作的主要内容,如果未能解决你的问题,请参考以下文章

服务器返回重定向 (302) 后,iOS 设备上的 AJAX 或 XHR 请求失败,代码为 0

Cordova 4.0 上的 Android 片段内的 Cordova webview

cordova ios 6.1.0 wkwebview 一些 xhr POST 失败

eclipse / Android上的Cordova phonegap

Android 应用 (Cordova) 上的文本区域中的字数超出限制

如果 Android (Cordova) 上的尺寸超过 256 像素,画布会闪烁