Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cordova - XHR Requests on Android work in Emulator, but not on Phones

so I have an existing app that has been on the app store for quite some time, as of 3 days ago I was getting more support enquiries saying my app could not connect to my service.

Now it has finally happened to me on my Android devices - everything works perfectly for iOS, and perfectly for Android on Emulator - but nothing in the real world.

I have looked as far as I can by step-debugging with Cordova and it passes the whitelist test fine. My very first XHR request works fine, but subsequent ones always fail until I completely close the app and re-open.

I am using [email protected] - I have also tried [email protected]

My Content-Security-Policy looks like this

<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'">

My Cordova config has

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

I have tried adding/removing/replacing the above/every combination with <access origin="*" /> but no luck.

My XHR response always looks like the following

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

I have step-debugged the XHR request as far as I could have in the Cordova Plugin, by step debugging out of the Whitelist.java but everything returns fine and it makes it successfully to the line

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

of function

WebResourceResponse shouldInterceptRequest(WebView view, String url)

in org.apache.cordova.engine.SystemWebViewClient.java

My Android Manifest has the following

<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" />

I am using [email protected], Cordova platform [email protected]

I've spent several hours trying to dig deeper, what am I missing here? Any help would be greatly appreciated!

like image 708
DdD Avatar asked Aug 05 '19 14:08

DdD


People also ask

How to debug Cordova iOS app?

To enable debugging on iOS, In the iOS device, go to Settings → Safari → Advanced → Enable 'Web Inspector' From the Mac, Safari → Preferences → Advanced → Enable 'Show Develop menu in menu bar' Once this is done, start the Cordova application and connect your iOS device with USB cable.

Do I need Android studio for Cordova?

Cordova-Android requires the Android SDK, which can be installed on either macOS, Linux, or Windows. For the base system requirements, see the Android Studio's System Requirements.

How to debug in Cordova?

First tap 7 times on the Build Number (is the last option too), then a message that "You're a developer now will appear". Followed, go back to the settings and you will see now a new available option in the menu. Tap on this and go to the last option (Debugging : USB Debug mode when usb is connected).


3 Answers

As the problem disappears if you lower the targetSDK, it's probably the usesCleartextTraffic mentioned by Nidhin Josehp. It only affects Android 8 or newer devices when targeting SDK 28 or greater.

Instead of manually editing the AndroidManifest.xml as he suggest (you should never manually edit it in Cordova apps) you can add this to the 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>

You might need to change your widget tag in config.xml to look something like this:

<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">

(The addition is the xmlns:android="http://schemas.android.com/apk/res/android")

like image 164
jcesarmobile Avatar answered Sep 23 '22 05:09

jcesarmobile


Try adding android:usesCleartextTraffic="true" to the <application> in the AndroidManifest.xml or as below using 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 Indicates whether the app intends to use cleartext network traffic, such as cleartext HTTP. The default value for apps that target API level 27 or lower is "true". Apps that target API level 28 or higher default to "false". More info

Cleartext is any transmitted or stored information that is not encrypted or meant to be encrypted. When an app communicates with servers using a cleartext network traffic, such as HTTP, it could raise a risk of eavesdropping and tampering of content which is why in latest Android devices, it's set to false by default.

like image 25
Nidhin Joseph Avatar answered Sep 21 '22 05:09

Nidhin Joseph


I'm going to jump I swear.

<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="26" />

Changed targetSdkVersion to 26 from 28. Worked. But this is going to be a nightmare.

But this is going to be a nightmare

Edit: Problem has come back but only for Samsung Galaxy Tablets. I can't replicate this behaviour anywhere else.

Edit2: Things are...fine again?

like image 28
DdD Avatar answered Sep 20 '22 05:09

DdD