I am trying to send a response from a fetch request using React-Native for client-side and Node/Express for the server. Unfortunately, the value is only displayed with iOS emulator and not with android. I came across an article in github https://github.com/facebook/react-native/issues/24627 suggesting to add some code on the AndroidManifest file but it is still not working, I tried devices from API 25 to 29 and it worked with none. Can someone please help? Thanks for your time.
Frontend
import React, { Component } from "react";
import {Modal, StyleSheet, View, StatusBar, Text} from 'react-native'
import { Provider } from 'mobx-react';
import StateStorage from './StateStorage';
export default class App extends React.Component {
constructor (props) {
super(props)
this.state ={
data:''
}
}
componentDidMount(){
this.callBackendAPI()
.then(res => this.setState({ data: res.express }))
.catch(err => console.log(err));
}
callBackendAPI = async () => {
const response = await fetch('http://localhost:5000');
const body = await response.json();
if (response.status !== 200) {
throw Error(body.message)
}
return body;
};
render() {
return (
<Provider store={StateStorage}>
<Text style={{top:100}}>{this.state.data}</Text>
</Provider >
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
});
Backend
const express = require('express')
const app = express()
const port = process.env.PORT || 5000;
app.get('/', (req, res) => {
res.send({ express: 'YOUR EXPRESS BACKEND IS CONNECTED TO REACT' })
}
)
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.mapp">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:usesCleartextTraffic="true"
tools:targetApi="28"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyD4Js3-PNHs1aL4XEmw6mAomblC2b4ys5s"/>
</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
2
Answers
I see 2 issues here:
Starting from API 28 unencrypted HTTP requests are blocked by default.
Switch to HTTPS or take a look to this answer if you want to enable them.
The android emulator runs behind a virtual router that isolates it from the development machine network, if you want to access it you have to use
10.0.2.2
instead of127.0.0.1
(orlocalhost
).Look at the Android Emulator networking documentation for further details.
To share more light on @bug answer, below steps can be taking and @bugs explanation is applied to these also.
Create a xml file, you can call network_security_config.xml or anything.
Content of network_security_cong.xml below:
Note: android:networkSecurityConfig="@xml/network_security_config"