David Canora
David Canora

Reputation: 119

How to share a local photo using React Expo Sharing.shareAsync?

I'm trying to share a local file in React Expo using Sharing.shareAsync(). Retrieved photo info using MediaLibrary.getAssetInfoAsync() (on Android):

"filename": "IMG_20200414_190459.jpg",
  "height": 2074,
  "id": "896",
  "localUri": "file:///storage/emulated/0/DCIM/Camera/IMG_20200414_190459.jpg",
  "location": null,
  "mediaType": "photo",
  "modificationTime": 1586905500000,
  "uri": "file:///storage/emulated/0/DCIM/Camera/IMG_20200414_190459.jpg",
  "width": 4608,

Calling Sharing.shareAsync(photo.localUri, {mimeType: 'image/jpeg'} I get the error Failed to share the file: Failed to find configured root that contains /storage/emulated/0/DCIM/Camera/IMG_20200414_190459.jpg. So I tried removing one of the slashes after file: and get the error Not allowed to read file under given URL.

App has CAMERA_ROLL and CAMERA permissions and app.json includes:

"android": {
      "permissions": [
        "CAMERA",
        "CAMERA_ROLL",
        "READ_EXTERNAL_STORAGE",
        "WRITE_EXTERNAL_STORAGE"
      ]
    }

Expo docs say I should be able to share a local file. Not sure what I'm doing wrong or what to try next. TIA.

Upvotes: 0

Views: 3190

Answers (2)

Adx
Adx

Reputation: 147

This is a problem with the share API. You can get over this using the expo-image-manipulation. As an example:

import * as ImageManipulator from "expo-image-manipulator";

const openShareDialogAsync = async () => {
    let imageProc = await ImageManipulator.manipulateAsync(yourImageUri);
    // this returns an object including the uri
    await Sharing.shareAsync(imageProc.uri);
}

Upvotes: 5

brentvatne
brentvatne

Reputation: 8038

It looks like this may be a bug in the Sharing API. You can work around it for now by copying the file to your document directory and then sharing from there. Here's an example: https://snack.expo.io/@notbrent/share-media-library-photo

Relevant code from that example below:

// Placeholder for getting asset from MediaLibrary
let results = await MediaLibrary.getAssetsAsync({ first: 1 });
let asset = results.assets[0];

// Use FileSystem to copy the image from its original location to the app document directory
let assetUriParts = asset.uri.split("/");
let assetName = assetUriParts[assetUriParts.length - 1];
let uri = `${FileSystem.documentDirectory}/${assetName}`;
await FileSystem.copyAsync({
  from: asset.uri,
  to: uri,
});

// Share the image from the uri that you copied it to
Sharing.shareAsync(uri);

Upvotes: 3

Related Questions