I am developing a React Native app using Expo and I recently ran into a weird issue. API requests don't work on Android devices however they're totally fine on iOS. The server I'm trying to connect to isn't localhost. I tried to use axios and fetch, both result in Network Error and the server doesn't receive a request. I also made requests to open APIs which got me the same error, so I believe the problem isn't on the server's side.
Here's the code of the request:
const axiosInstance = axios.create({
timeout: 120000,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
})
const res = await axiosInstance.post(`${serverHostApi}/merchant/login`, payload)
Here's the stack trace:
Network Error
- node_modules\axios\lib\helpers\normalizeHeaderName.js:8:14 in processHeader
* http://192.168.150.71:19001/node_modules%5Cexpo%5CAppEntry.bundle?platform=android&dev=true&minify=false&hot=false:226876:26 in handleError
- node_modules\event-target-shim\dist\event-target-shim.js:818:20 in EventTarget.prototype.dispatchEvent
- node_modules\react-native\Libraries\Network\XMLHttpRequest.js:575:10 in setReadyState
- node_modules\react-native\Libraries\Network\XMLHttpRequest.js:389:6 in __didCompleteResponse
- node_modules\react-native\Libraries\vendor\emitter\EventEmitter.js:189:10 in emit
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:425:19 in __callFunction
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:112:6 in __guard$argument_0
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:373:10 in __guard
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:111:4 in callFunctionReturnFlushedQueue
* [native code]:null in callFunctionReturnFlushedQueue
I'm using Expo 38.0.0, React Native SDK 38.0.2.
Any help would be highly appreciated!
If this is happening only in the android app. It might be a case you accidently removed internet permission from your android app. Kindly check you have proper permission in the Android Manifest File.
To Check , go the YourApp/android/app/src/main and open AndroidManifest.xml
and check if you have this line
<uses-permission android:name="android.permission.INTERNET" />
if you don't have it , add this line inside your Manifest file like this
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
I also ran into this problem.
You can use tools like SSL Labs to test the validity of your SSL certificate.
SSL SERVER TEST
I solved it with this method
Only way that I found to resolve is downgrade the version. Or you should make sure that TLS 1.0 and TLS 1.1 is disabled on the server.
"axios": "0.24.0"
Related
I'm building an ionic application and I faced with an issue that affect only the Android devices.
I have some public images that I'd like to load like this:
<img src={imageurl} alt="" />
I'm using this plugin https://github.com/capacitor-community/http to make API calls, to avoid CORS issues. All the API calls are working on both platforms, but the images only works on iOS.
If I check the inspector this is the error message I get:
If I check the Android Studio logs I see these error messages: E/Capacitor: Unable to open asset URL:
If I'm using axios to make the API calls it works fine on Android but then it'll break on iOS due to CORS issues.
I was trying to separate the API calls and only use the native plugin on iOS but I don't think that is possible.. Android was able to make the calls with axios but response was always got response like this:
Android AndroidManifest is extended with this: android:usesCleartextTraffic="true"
webDir: "build",
bundledWebRuntime: false,
android: {
allowMixedContent: true
},
server: {
cleartext: true,
hostname: "baseurl.hu",
iosScheme: "localhost",
androidScheme: "https"
},
This is how I run the app:
ionic capacitor copy android
Android Studio run.
I have an application Ionic Capacitor Angular that is simply getting the GeoLocation and displaying the lat lng on screen
async ngOnInit(){
await Geolocation.getCurrentPosition({
enableHighAccuracy: true
}).then((resp) => {
this.latitude = resp.coords.latitude;
this.longitude = resp.coords.longitude;
this.options = {
center: { lat: this.latitude, lng: this.longitude},
zoom: 17
};
}).catch((error) => {
console.log('Error getting location', error);
});
}
This runs perfectly fine in the browser with Ionic Serve. I have also successfully launched it on a device(Samsung S9) which is Android V9 (knox api level 27). However when I run it on a (Samsung S21 Ultra) which is Android V11 (knox api level 33)
I have the following within the AndroidManfiest.xml of the app
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_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.ACCESS_BACKGROUND_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
I see this in the documentation
Caution: If your app targets Android 11 (API level 30) or higher, the system enforces this best practice [ asking for foreground and background access in separate requests ]. If you request a foreground location permission and the background location permission at the same time, the system ignores the request and doesn’t grant your app either permission
I have not been able to find a resolution to this issue. Can someone please help provide some insight. Again this is actual hardware and not an emulator.
So it looks like this is an issue with Cordova and Google Play Services. Version 21.30.16 of Google Play Services looks to have introduced this bug.
https://github.com/ionic-team/capacitor/issues/4962
This seems to be a viable solution for Capacitor 2 until it is officially patched:
Updated Answer
As of Sept 10, 2021 Capacitor v2.5.0 contains the patch outlined below, but it is suggested that if possible upgrade to Capacitor v3 which also contains a patch and will receive bug patches unlike Capacitor v2.x.
Original Answer
For now I've manually made the changes in #4992 to
node_modules/#capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/Geolocation.java
and used patch-package so we can hotfix our app. We can then remove
the patch if the fix lands in Capacitor v2 or when the day comes that
we upgrade to v3.
The steps we just applied using patch-package:
Access #capacitor/android and update Geolocation.java using this PRs changes (https://github.com/ionic-team/capacitor/pull/4992/files)
Run npx patch-package #capacitor/android
Update package.json with "postinstall": "patch-package"
npm install patch-package so dependency exists when npm install is run during Ionic AppFlow
Commit the patch file and changes to package.json
(Optional) If you get an error like "cannot run in wd [...]" add a .npmrc with unsafe-perm = true if you can't use a non-root user, for example when using Ionic AppFlow to build and deploy
I am getting a Network request failed when trying to fetch from localhost in ReactNative for both android and ios devices.
I've tried following previous solutions but nothing seemed to work for me. I followed this tutorial: https://revs.runtime-revolution.com/connecting-react-native-to-localhost-65e7ddf43d02
For iOS:
I edited the info.plist and added the following code and reinstalled the app on my simulator but it still didn't work.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
For Android:
I used my IP instead of 'localhost' for my fetching URL but it still didn't work. I also made configurations to AndroidManifest.xml following the steps in the tutorial but it still doesn't work.
Any other solutions???
PS. I am using a Macbook. My REST API is using SQL database and asp.net core. I am trying to fetch a json.
Error: Network Request Failed
Fetch code:
async getProjects1() {
const response = await fetch('https://127.0.0.1:5001/api/projects');
const data = await response.json();
this.setState({ projects: data, loading: false }, function(){console.log(this.state.projects)});
};
Your error message says that there is unhandled promise rejection, so i'd advise adding error handling as:
async getProjects1() {
try {
const response = await fetch('https://127.0.0.1:5001/api/projects');
const data = await response.json();
this.setState({ projects: data, loading: false }, function(){console.log(this.state.projects)});
} catch (err) {
console.log(err)
}
}
and this issue may be resolved, or you at least might get clearer error message.
I solved the issue. The error was not because of react native but from my asp.net core API. Basically, I just needed to change my code in the launchsettings.js in the Properties folder from "applicationUrl": "https://localhost:5001;http://localhost:5000" to "applicationUrl": "http://localhost:5000"
This solved the issue and fetching from localhost in react native worked without any further issues. This stack question helped me figure this out: How to fix network error in react-native when access localhost api
These solutions did not work.
What did work:
Download ngrok (https://ngrok.com/), signup, and connect your account. ngrok creates a private https localhost tunnel.
Setup - https://dashboard.ngrok.com/get-started/setup
Unzip to install ngrok:
unzip /path/to/ngrok.zip
Connect your ngrok account (Non functioning example auth token):
ngrok config add-authtoken 2ySPR5UeS3Fjf5YAblNRe7ZcV1o_9sdf2SDFGHjEQaOCE6xEi
Use the command (with your port number):
ngrok http 8080
Once ngrok is online, replace your localhost API address:
http://localhost:8080
http://127.0.0.1:8080
http://192.168.0.100:8080
With the forwarding web address (Non functioning example address):
https://ebda-61-137-45-130.ngrok.io
I've used ngrok for testing APIs on a variety of networks without issue. So far its the only foolproof method I've found for testing APIs using localhost.
Tried to create user account through https POST request under react-native with axios, while it always failed on android with a 'network error'.
axios('https://'+DEST_URI, {
method: 'post',
data: account,
headers: {
'Accept': 'application/json',
}
then(...)
The same https POST request works fine on iOS.
Changed to http, the same POST request works on android as well.
Also tried GET request through https on android, it could retrieve data from the backend server as expected.
Any idea about it?
Linked image is the output from console log,
output from console log
I was facing the same issue with android 'POST' requests. Turned out to be headers issue as mentioned in the link: https://github.com/facebook/react-native/issues/5222#issuecomment-170239302
Adding the following headers fixed the issue for me
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer ' + this.authToken,
'Content-Type': 'application/x-www-form-urlencoded',
}
Related to the issue Upgrade to OkHttp3 on the react-native repository.
Deactivate http2 from your proxy that is what causing the problem.
You can try to upgrade to react-native v0.27 they mention in the change log that they fixed this problem but for me didn't work.
I had to disable the http2 feature in ngnix to make it work.
disabling http2 really is this simple, just change this line in your ngnix config file from:
listen 443 ssl http2;
to
listen 443 ssl;
then reload your config:
service nginx reload
More info about http2 and ngnix can be found here
I guess you have not a internet permission in your AndroidManifest.xml file.
Please add this line into you AndroidManifest.xml file:
<uses-permission android:name="android.permission.INTERNET" />
I'm creating android application in Cordova witch consume a REST service using AngularJs,
I test this application first on browser by this URL
file:///C:/Users/Users/MyApps/project/platforms/android/assets/www/index.html#/demande/list but that stil give this Error :
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at
http://10.0.2.2:8080/springrestprojet/rest/demande. Reason: CORS request failed.
I'm sing CORS filter for enabling access.
this is my code of service.js :
'use strict';
angular.module('workflowService', ['ngResource']).
factory('Demande', function ($resource) {
return $resource('http://10.0.2.2:8080\:8080/springrestprojet/rest/demande/:id', {}, {
'save': {method:'PUT',
headers: {'Content-Type': 'application/json',
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS, PUT',
'Access-Control-Request-Method':'*',
'Access-Control-Allow-Headers':'*',
'Accept': 'application/json'}},
});
});
Any help please ?
Thanks a lot.
Since a few months, the access origin="*" is not enough.
Try to install this plugin sudo cordova plugin add https://github.com/apache/cordova-plugin-whitelist
And then, in your config.xml add a line like that one
<allow-navigation href="*" />
The * isn't recommended, but it'll work for everything. You can specify the path like this http://yourWebSite.com/*
I suspect that in latest versions the plugin cordova-plugin-whitelist requires to configure the meta http-equiv="Content-Security-Policy" in each html file of your project.
With first version it only displayed warnings, but considering several questions seen here, maybe the behaviour has changed...
So you have two solutions :
remove the plugin cordova-plugin-whitelist and add instead cordova-plugin-legacy-whitelist then cordova will behave like with cordova 3.x where only access origin was checked (not recommended regarding security)
or you learn about Content-Security-Policy, for example by reading this page and update your htmls.
More info on Raymond Camden's blog or in the plugin's documentation.
Edit: now I remember, it's not that it changed in latest version it's that content security policy is checked on android starting with Kit-Kat, so a same app with cordova-plugin-whitelist and no CSP configured would work in android < 4.4 and fail in 4.4+.
So note to all cordova/phonegap developers, test your CSP code in kitkat or lolypop or you may have bad surprises!