React Native Example - Profile Image Upload

I would like to see a working example of updateCurrentUserInfoWithProfileImage, for both Android and iOS. I am continually getting the cryptic error message [SendBirdException: Request failed.] for Android profile file uploads. It’s working for iOS, but not Android. Does anyone have an example here? I can’t go any further without a better error message!

Hey @fullStackChris,

The example I provided you in our last conversation was tested on Android.

This code works for fileMessage. But it does not work for updateCurrentUserInfoWithProfileImage. To be clear I tried the same exact process with fileMessage:

const result = await DocumentPicker.pick({
        type: [
          DocumentPicker.types.images,
          DocumentPicker.types.video,
          DocumentPicker.types.audio,
          DocumentPicker.types.plainText,
          DocumentPicker.types.zip
        ]
      });
      const copyPath = `${RNFS.TemporaryDirectoryPath}/${result.name}`;
      await RNFS.copyFile(result.uri, copyPath);

      const fileStat = await RNFS.stat(copyPath);
      const params = new sendbird.FileMessageParams();
      params.file = {
        ...result,
        uri: `file://${fileStat.path}`
      };

(Actually, I don’t know what version of DocumentPicker this example was from, because result is an array, so you need to index result to get at any actual file values. In my example I just choose the first document picked, i.e. result[0])

in the case of updateCurrentUserInfoWithProfileImage I simply create const file:

const file = {
      type: result[0].type,
      uri: `file://${fileStat.path}`,
      name: result[0].filename
};

Logging the file out before I send it yields something like this:

{
    "name": "test.png", 
    "type": "image/png", 
    "uri": "file:///data/user/0/ch.inclub.staging/cache/test.png"
}

Which looks completely fine to me, and how it looks in iOS. My guess is some file permission issue in Android.

I would disagree with that. In both the written sample I provided, and the video, I wrote it using the updateCurrentUserInfoWithProfileImage instead of sending a file message.

Here is the code once more:

const selectFile = async () => {
      if (Platform.OS === 'android') {
        const permission = await check(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE);
        if (permission !== RESULTS.GRANTED) {
          const result = await request(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE);
          if (result !== RESULTS.GRANTED) {
            throw new Error('Please allow the storage access permission request.');
          }
        }
      } else if (Platform.OS === 'ios') {
        // TODO:
      }
      const result = await DocumentPicker.pick({
        type: [
          DocumentPicker.types.images,
          DocumentPicker.types.video,
          DocumentPicker.types.audio,
          DocumentPicker.types.plainText,
          DocumentPicker.types.zip
        ]
      });
      const copyPath = `${RNFS.TemporaryDirectoryPath}/${result.name}`;
      await RNFS.copyFile(result.uri, copyPath);

      const fileStat = await RNFS.stat(copyPath);
      sb.updateCurrentUserInfoWithProfileImage('iOSTest01', {
        ...result,
        uri: `file://${fileStat.path}`
      });

Here is also the video once more:

You can see the profile image update with the file I upload.

It does look like its using an older version of Document Picker "version": "3.5.4", which appears to be about a year old.

In terms of iOS vs Android, is it the same image you’re using in both devices to test? Additionally, do you have any type of image moderation enabled within your application?

1 Like

Just downgraded my react-native-document-picker to match at 3.5.4, but that also didn’t bring any help.

After the downgrade, I checked with the same image in iOS, it’s working, though I am able to use the sourceURL as mentioned in my other post Incorrect Mimetype for profile_file Upload - JavaScript SDK - #6 by Tyler

At first I was considering it could be because of the image, it is quite large at 3000x3000 - but alas, it still works with iOS.

Are you able to print out the produced object there for the file? Mine currently looks like this:

{"fileCopyUri": "content://com.android.providers.media.documents/document/image%3A36", "name": "avataaars (2).png", "size": 47039, "type": "image/png", "uri": "file:///data/user/0/my.app.identifier/cache/avataaars (2).png"}

Now I am wondering if it has to do with differing version of react-native-fs or even react-native. What versions do you have for those two packages?

Also, your example video is a simulator, correct? Though I guess that is not the cause, it’s not working in android simulator or real android phones…

How can I check for image moderation in the dashboard? I don’t see it anywhere…

Hey Chris,

You can take a look at image moderation here: Filter and moderation | Chat Platform API | Sendbird Docs

As for the versions I’m using, you can see the entire code base utilized in my video here: SendBird-JavaScript/package.json at master · sendbird/SendBird-JavaScript · GitHub

Its our hook-sample application for React-Native. The only thing I did was update function found here: SendBird-JavaScript/chat.js at 7c91e9d91b1210015a52f4abe064524e3333792e · sendbird/SendBird-JavaScript · GitHub

I updated its call to send a fileMessage to instead use updateCurrentUserInfoWithProfileImage

If you download the sample application, and connect it to your Sendbird App ID, are you able to reproduce the error you’re seeing?

1 Like

Well, now I’m totally stumped. Here’s what I did:

  • Downloaded and installed the sample, making the code changes needed and adding our own App ID.

  • The profile image upload works there!

  • On our own app - I matched react-native-fs, react-native-document-picker, and even sendbird to the versions as in the example app. There were some configuration steps in the android native files I was missing for react-native-fs, those have been added.

  • I’ve examined the file data for the same image before it is passed to the updateCurrentUserInfoWithProfileImage - they are identical between the sample app and our app.

That must mean the issue is hiding somewhere in our app, but I can’t see how. At this point, the code is literally 1:1 with what is working in the example app, including all involved packages. I realized one can JSON.stringify the error in the callback, here’s what I get:

{"name":"SendBirdException","code":800220,"line":110402,"column":19,"sourceURL":"http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=my.app.identifier&modulesOnly=false&runModule=true"}

So perhaps it is on Sendbird’s side - 800220 is The server failed to process the request due to an internal reason.

The one final thing to check is how you put images on your simulator. I simply drag and drop them, and when the document picker opens, I see them under “recent files”. Seems pretty standard.

I too dragged and dropped images into my simulator. What version of Android is your simulator running?

Currently, I’ve been using a Pixel 3 XL with API 30, Android 10.0+

Hi Tyler, another week begins :grinning_face_with_smiling_eyes:

One last thing I thought might be an issue is that in other areas of my code I sometimes get an error of “there is a query in progress” if there are open queries to things like channels or chat messages. I’m assuming in the background this has to do with how sendbird is connected via a websocket, so if during the relatively slower profile upload, a single query is made in some side effect elsewhere in our app, that could interrupt the upload connection and cause the upload to fail (again, these are all just guesses / assumptions).

Is there a way to ensure that all current queries are canceled and that my single request is the profile picture upload?

Thanks again for your assistance.

Hi @fullStackChris,

Query in progress is an error that occurs when any type of query is made when one is already in progress. This would only be for fetching topics, and is not related to the updateCurrentUserInfoWithProfileImage method.

This typically occurs when calling next() when the previous query hasn’t finished.

Okay, that’s good to hear.

We are continually seeing the 800220 errors on android still - which makes me believe it is an issue on Sendbird’s side - is there any more information we can get on what is wrong? We’ve also recently turned off all image moderation and filtering in order to eliminate that variable.

Can you DM me your Application ID and the User ID of a sample user where you’ve received this error? I’ll see if I can track it down to see why it failed.

Hi Tyler,

I’ve finally figured it out!!! Long story short, it turns out that a dev-only Flipper network interceptor (and thus also the staging versions of app I was shipping out to android testers) messes specifically with these type of single file uploads. See this comment in this GitHub issue here:

As soon as I comment out that line in Flipper interceptor, uploads are working beautifully and as expected with Android devices!!!

Thanks for all your diligence and effort here.

Really an annoying solution in the end, but that’s usually how stuff like this turns out :slight_smile:

Hope this helps anybody who may find it or run into it in the future.

1 Like

Glad to hear you were able to track it down. Definitely an odd issue to say the least.

1 Like