3

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"/>
Camille Basbous
  • 299
  • 5
  • 11
  • 34
  • Please confirm if the issue was resolved with @bug 's answer – Zohaib Amir Nov 16 '19 at 11:41
  • If you have deployed your server on your local machine, you should be on same network with your server. Also share your android code to understand what you are getting on your device. – Haris Qurashi Nov 21 '19 at 13:17

2 Answers2

3

I see 2 issues here:

  1. 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.

  2. 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 of 127.0.0.1 (or localhost).
    Look at the Android Emulator networking documentation for further details.

bug
  • 3,900
  • 1
  • 13
  • 24
  • what about <28 ? is there a reason why it isnt working? – Camille Basbous Nov 13 '19 at 22:32
  • @CamilleBasbous for <28 this is **not enforced**, i.e it would still work on older devices but newer devices wouldn't allow it – Zohaib Amir Nov 16 '19 at 11:35
  • But it isn't working when I try that's the issue here. So the issue isn't resolved – Camille Basbous Nov 16 '19 at 16:12
  • Hi @CamilleBasbous, sorry for coming back to you late. I noticed another potential issue, basically you can't use localhost to access your development machine from the Android emulator. Please look at my updated answer for further details. – bug Nov 16 '19 at 21:17
  • @bug thanks for your reply I will check it out when I get back on this project, atm I have my focus elsewhere – Camille Basbous Nov 18 '19 at 04:51
0

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:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">10.0.2.2</domain>
        <domain includeSubdomains="true">https://your_api_url_ssh_support</domain>
        <domain includeSubdomains="true">http://your_api_url</domain>
    </domain-config>
</network-security-config>

Sample real network_security_config.xml can look like below:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">10.0.2.2</domain>
        <domain includeSubdomains="true">https://18.222.76.221</domain>
        <domain includeSubdomains="true">http://18.222.76.221</domain>
    </domain-config>
</network-security-config>

Then your manifest file trimmed down to what matters to this question:

<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:networkSecurityConfig="@xml/network_security_config"
      android:usesCleartextTraffic="true"
      tools:targetApi="28"
      android:theme="@style/AppTheme">
 
    </application>

Note: android:networkSecurityConfig="@xml/network_security_config"

And also note that to access the real address of your android emulator is why we have to point to 10.0.2.2 as explained by @bug.

Did I forget to mention that the network_security_config.xml will be placed in the res directory inside xml folder. So, it looks something like this: res->xml->network_security_config.xml Happy coding.

Community
  • 1
  • 1
Wale
  • 1,644
  • 15
  • 31