5

I'm developing react native expo application which takes photo using expo-image-picker and saves that image into a different location by using expo-media-library.

Everything seems to be working fine but this pop up keeps getting every time user captures the image. This keeps happening on Android. It's affecting UX.

It would be great if you guys could help me to sort out this issue. Thanks

Allow Expo Go to modify this photo?

Versions

"react-native": "0.64.3"

"expo": "~44.0.0"

"expo-image-picker": "~12.0.2"

"expo-media-library": "~14.0.0"

Here is the code which I'm using to archive mentioned functionality.

import * as ImagePicker from "expo-image-picker";
import * as MediaLibrary from "expo-media-library";

const savePhoto = async (data, onSucess) => {
  const asset = await MediaLibrary.createAssetAsync(data?.uri);
  const album = await MediaLibrary.createAlbumAsync(
    "TEST_FOLDER",
    asset,
    false
  );
  const albumAssets = await MediaLibrary.getAssetsAsync({
    album: album,
    first: 1,
    sortBy: [[MediaLibrary.SortBy.creationTime, false]],
  });
  if (albumAssets?.assets[0]) {
    onSucess(albumAssets.assets[0], data);
  }
};

const takePicture = async (onSucess, onError) => {
  let data = await ImagePicker.launchCameraAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.Images,
    quality: 0.8,
    allowsEditing: true,
    base64: true,
  });
  if (data.cancelled === false) {
    savePhoto(data, onSucess);
  } else {
    onError();
  }
};

And here is the app.json file.

{
  "expo": {
    "name": "product",
    "slug": "product_frontend",
    "version": "1.0.0",
    "orientation": "landscape",
    "icon": "./assets/images/icon.png",
    "userInterfaceStyle": "automatic",
    "splash": {
      "image": "./assets/images/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "plugins": [
      [
        "expo-media-library",
        {
          "photosPermission": "Allow $(PRODUCT_NAME) to access your photos.",
          "savePhotosPermission": "Allow $(PRODUCT_NAME) to save photos.",
          "isAccessMediaLocationEnabled": "true"
        }
      ],
      [
        "expo-image-picker",
        {
          "cameraPermission": "Allow $(PRODUCT_NAME) to access your camera",
          "photosPermission": "The app accesses your photos to let you share them with your friends."
        }
      ]
    ],
    "updates": {
      "fallbackToCacheTimeout": 0
    },
    "assetBundlePatterns": ["**/*"],
    "ios": {
      "supportsTablet": true
    },
    "android": {
      "package": "com.comapny.product",
      "adaptiveIcon": {
        "foregroundImage": "./assets/images/adaptive-icon.png",
        "backgroundColor": "#FFFFFF"
      },
      "softwareKeyboardLayoutMode": "pan",
      "permissions": []
    },
    "web": {
      "favicon": "./assets/images/favicon.png"
    },
    "scheme": "product"
  }
}

It would be great if you guys cold help me to sort out this issue. Thanks.

Nullish Byte
  • 354
  • 2
  • 10
  • I would also want to know how to solve this. Another question related to this https://stackoverflow.com/questions/72025673/allow-expo-go-to-modify-this-photo-modal-window – Aeriel Feb 16 '23 at 06:23
  • Anyone find a solution for this? – Bo rislav Feb 21 '23 at 08:07

1 Answers1

0

I also had this issue and believe I found a workaround.

When you call createAlbumAsync you can pass true. This will copy the asset data and not move or modify it, which is causing the android pop-up. You can then import and use expo-file-system to delete the original image if that matters to you. See my code below:

import * as ImagePicker from 'expo-image-picker';
import * as MediaLibrary from 'expo-media-library';
import * as FileSystem from 'expo-file-system';

const takePhoto = async () => {
    let asset = {};
    let data = await ImagePicker.launchCameraAsync();
    const permission = await MediaLibrary.requestPermissionsAsync();
    if (!data.cancelled) {
      if (permission.granted) {
        try {
          // create an asset using the imagePicker data uri, on android a folder cannot be created without a pre-existing asset
          asset = await MediaLibrary.createAssetAsync(data.uri);
          // getAlbumAsync returns null if no album is found
          const existingFolder = await MediaLibrary.getAlbumAsync(
            'AlbumName'
          );
          // if the album doesn't exist, create it
          if (!existingFolder) {
              await MediaLibrary.createAlbumAsync(
              'AlbumName',
              asset,
              // passing true copies the file and doesn't move it, moving it is what triggers the android modify popup
              true
            );
            // since the file is copied and not moved we can then delete the original after
            await FileSystem.deleteAsync(data.uri);
          } else {
            // if the album exists add the asset to it
            // similar to createAlbumAsync, passing true copies the file and doesn't move it, so again we delete the original after
            MediaLibrary.addAssetsToAlbumAsync(asset, existingFolder.id, true);
            await FileSystem.deleteAsync(data.uri);
          }
        } catch (error) {
          console.log(error);
        }
      } else {
        console.log('Storage permissions must be enabled to save file');
      }
  }
}

Hope this helps!