React Native Expo: Network error on android
Asked Answered
A

7

5

I'm using axios in my app. When I make a post request for the very first time after opening the app, it is failing with the following error. From second time onwards, it works without any issue.

Network Error
- node_modules/axios/lib/core/createError.js:15:17 in createError
- node_modules/axios/lib/adapters/xhr.js:81:22 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:600:10 in setReadyState
- node_modules/react-native/Libraries/Network/XMLHttpRequest.js:395:6 in __didCompleteResponse
- node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js:189:10 in emit
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:416:4 in __callFunction
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:109:6 in __guard$argument_0
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:364:10 in __guard
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:108:4 in callFunctionReturnFlushedQueue
* [native code]:null in callFunctionReturnFlushedQueue

I'm running on a real android device connecting to a real server by http://my_ip:my_port/. Same post request I tried by creating a Native android project in kotlin, and it is working without any issue

Here is my code:

const upload = () => {
    setAnalyzing(true);

    axios.post(URL_PREDICT, formBody(), {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    }).then(handleSuccess)
      .catch(handleFail);
  }

  const formBody = () => {
    const photo = {
      uri: image,
      type: 'image/jpeg',
      name: 'photo.jpg',
    };
    const form = new FormData();
    form.append("file", photo);
    return form;
  };

  const handleFail = (error) => {
    console.log(error)
    console.log(error?.response?.data);
    setAnalyzing(false);
    toggle();
    alert("ERROR " + error);
  };

  const handleSuccess = response => {
    console.log('success...');
    setAnalyzing(false);
    toggle();
    console.log(response);
    navigation.navigate('Result', response);
  };

Any idea whats causing this?

Applewhite answered 13/1, 2021 at 7:59 Comment(1)
http might be the issue here. Try using https with a valid domain certificate. Also please share your package.json.Viminal
S
9

I think you are using expo-image-picker.

There are two independent issues at action here. Let’s say we get imageUri from image-picker, then we would use these following lines of code to upload from the frontend.

const formData = new FormData();
formData.append('image', {
 uri : imageUri,
 type: "image",
 name: imageUri.split("/").pop()
});

The first issue is with the imageUri itself. If let’s say photo path is /user/.../path/to/file.jpg. Then file picker in android would give imageUri value as file:/user/.../path/to/file.jpg whereas file picker in iOS would give imageUri value as file:///user/.../path/to/file.jpg.

The solution for the first issue is to use file:// instead of file: in the formData in android.

The second issue is that we are not using the proper mime-type. It is working fine on iOS but not on Android. What makes this worse is that the file-picker package gives the type of the file as “image” and it does not give proper mime-type.

The solution is to use proper mime-type in the formData in the field type. Ex: mime-type for .jpg file would be image/jpeg and for .png file would be image/png. We do not have to do this manually. Instead, you can use a very famous npm package called mime.

The final working solution is:

import mime from "mime";

const newImageUri =  "file:///" + imageUri.split("file:/").join("");

const formData = new FormData();
formData.append('image', {
 uri : newImageUri,
 type: mime.getType(newImageUri),
 name: newImageUri.split("/").pop()
});
Squarrose answered 19/1, 2021 at 9:50 Comment(1)
That uri difference in android and ios has resolved I guess, because the uri in my android is already starts with "file:///"Fortalice
G
11

Solution 1

Make Sure "http://" is in your URL Address .

  1. change from localhost to your ip
  2. add http://

http://192.168.43.49:3000/user/

Solution 2

I faced same issue, it happens in Android, but works well in IOS. I guess this issue about Flipper Network.

For while, I commented

initializeFlipper(this, getReactNativeHost().getReactInstanceManager())

in this file /android/app/src/main/java/com/{your_project}/MainApplication.java

Solution 3

Whoever is still struggling with this issue. it's happening because of Flipper network plugin. I disabled it and things work just fine.

My workaround to make this work is commenting out line number 43

38      NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
39      NetworkingModule.setCustomClientBuilder(
40          new NetworkingModule.CustomClientBuilder() {
41            @Override
42            public void apply(OkHttpClient.Builder builder) {
43      //        builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
44            }
45          });
46      client.addPlugin(networkFlipperPlugin);

in this file android/app/src/debug/java/com/**/ReactNativeFlipper.java

Solution 4

don't need to add Access-Control-Expose-Headers.

Need this:

                headers:{
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Accept': 'application/json'}
            }

And I adjust your server,it works.

Gisarme answered 18/1, 2021 at 5:40 Comment(4)
Solution 1: Yes, base url is correct. It has http, not using localhost, using ip only. As I mentioned in the question, it errors out only the first time I'm making the request. Basically in my app, I've a button which when clicked makes the api call. It errors out the first time. when I click the button again, the same api call works. Solution 2 and 3 doesn't apply to me since I'm using expo. There is no android folder. Correct me If I'm wrong. I'm new to react-native Solution 4: I do not understand what you mean. Could you be kind to explain?Applewhite
@DrunkenDaddy can you provide reproducible example code from the GitHub repo? so I can fix it for youGisarme
Ah damn it, faced this error before but forgotten about it again. Works when I change localhost to my ip address; Eg http:localhost:4000/api -> http:192.168.1.69:4000/apiKynewulf
Changing localhost to IP address worked for me!Jandel
S
9

I think you are using expo-image-picker.

There are two independent issues at action here. Let’s say we get imageUri from image-picker, then we would use these following lines of code to upload from the frontend.

const formData = new FormData();
formData.append('image', {
 uri : imageUri,
 type: "image",
 name: imageUri.split("/").pop()
});

The first issue is with the imageUri itself. If let’s say photo path is /user/.../path/to/file.jpg. Then file picker in android would give imageUri value as file:/user/.../path/to/file.jpg whereas file picker in iOS would give imageUri value as file:///user/.../path/to/file.jpg.

The solution for the first issue is to use file:// instead of file: in the formData in android.

The second issue is that we are not using the proper mime-type. It is working fine on iOS but not on Android. What makes this worse is that the file-picker package gives the type of the file as “image” and it does not give proper mime-type.

The solution is to use proper mime-type in the formData in the field type. Ex: mime-type for .jpg file would be image/jpeg and for .png file would be image/png. We do not have to do this manually. Instead, you can use a very famous npm package called mime.

The final working solution is:

import mime from "mime";

const newImageUri =  "file:///" + imageUri.split("file:/").join("");

const formData = new FormData();
formData.append('image', {
 uri : newImageUri,
 type: mime.getType(newImageUri),
 name: newImageUri.split("/").pop()
});
Squarrose answered 19/1, 2021 at 9:50 Comment(1)
That uri difference in android and ios has resolved I guess, because the uri in my android is already starts with "file:///"Fortalice
R
2

If someone doesn't like the upvoted answer or is still facing the issue, then my answer might help. Make sure your emulator/device time is same as real world time to avoid certificate validation error, otherwise manually set the correct time and reload the app.

Ref answered 15/6, 2021 at 9:51 Comment(0)
Y
2

In case anyone is having trouble with this again.. I found that for android the ip needed to be 10.0.2.2 but for ios it needed to be 127.0.0.1.

The code below allows you to set them independently:

import { Platform } from 'react-native';

const LOCALHOST = Platform.OS === 'ios' ? 'http://127.0.0.1:8000' : 'http://10.0.2.2:8000';
export const API_BASE_URL = LOCALHOST + '/api/v1/';
Yuzik answered 20/7, 2023 at 13:6 Comment(1)
This worked for me. How did you even find this out lol. Thanks!Allegory
A
0

I had the same problem when trying to send an API request from an react native application using expo in a emulator to my rust actix web server. After spending several hours into the issue and not being able to find the way to fix it, I found the solution in ngrok. It makes a tunnel from your local server to open web, so basically yo can call from your RN app to your api endpoint as if it would not be running in your localhost.

The error was fixed, instantly. Hope it helps, even if I am aware that is not a fix, but a workaround to your problem.

Australian answered 29/3, 2023 at 16:18 Comment(0)
S
0

I'm still experiencing this issue as of Nov 2023, and none of the solutions here works.

Using FileSystem's uploadAsync works perfectly, only downside to this is that it doesn't allow multiple file upload which is a deal breaker for me.

npx expo install expo-file-system

if you are only uploading a single file, then you could use this snippet


import {uploadAsync} from "expo-file-system"
import axios from "axios"

let url = "" // your endpoint
let image = {} //imagePickerResult;
let sendData = {} // Plain object
let formData = new FormData(); // sendData  keys and values appended to formdata plus the image
 
if (Platform.OS == "android") {
    let res = await uploadAsync(url, image.uri, {
        fieldName: "nameOfField", 
        httpMethod: "PATCH", 
        mimeType: "image/*", 
        uploadType: FileSystemUploadType.MULTIPART, 
        headers: {
            // access token bearears auth and what-not
        }, 
        parameters: sendData // This would be the BODY of the request
    })
    return res
} else {
    let res = await axios.patch(url, formData);

    return res
}

Speedway answered 22/11, 2023 at 13:45 Comment(0)
L
0

To resolve the "Network Error" issue when opening the Expo app, you can follow these steps:

1)Open the Windows Security app by searching for it in the Start menu. 
2) Go to Firewall & Network Protection. 
3)Under Public Network (active), click on it to manage settings. 
4)Turn off the Microsoft Defender Firewall for the public network. 
5)This should resolve the network error.

Additionally, if you're using a mobile phone that's connected to your PC and running Expo Go on the same device, this solution should help you run your project smoothly.

Lear answered 16/10 at 7:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.