skip to Main Content

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


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

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search