2

I want users to be able to take photos from within my app and have the photos save to their gallery (so that I can later view them in a photo-picker).

I have the following code from react-native-camera, it's basically the bare-bones demo code.

takePicture() {
    const options = { quality: 0.5, fixOrientation: false, width: 1920 };
    if (this.camera) {
      this.camera
        .takePictureAsync(options)
        .then(data => {
             this.saveImage(data.uri);
        })
        .catch(err => {
          console.error("capture picture error", err);
        });
    } else {
      console.error("No camera found!");
    }
  }
}

To move the attachment, I am using react-native-fs, as follows (more basic demo-y code):

const dirHome = Platform.select({
  ios: `${RNFS.DocumentDirectoryPath}/Pictures`,
  android: `${RNFS.ExternalStorageDirectoryPath}/Pictures`
});

const dirPictures = `${dirHome}/MyAppName`;

saveImage = async filePath => {
    try {
      // set new image name and filepath
      const newImageName = `${moment().format("DDMMYY_HHmmSSS")}.jpg`;
      const newFilepath = `${dirPictures}/${newImageName}`;
      // move and save image to new filepath
      const imageMoved = await this.moveAttachment(filePath, newFilepath);
      console.log("image moved: ", imageMoved);
    } catch (error) {
      console.log(error);
    }
  };

  moveAttachment = async (filePath, newFilepath) => {
    return new Promise((resolve, reject) => {
      RNFS.mkdir(dirPictures)
        .then(() => {
          RNFS.moveFile(filePath, newFilepath)
            .then(() => {
              console.log("FILE MOVED", filePath, newFilepath);
              resolve(true);
            })
            .catch(error => {
              console.log("moveFile error", error);
              reject(error);
            });
        })
        .catch(err => {
          console.log("mkdir error", err);
          reject(err);
        });
    });
  };

When taking a photo, this code executes and prints that the image has been moved within a couple of seconds. But, when I look into the built in Gallery App on the device, it often takes several minutes for the image to finally load. I've tried this across many different devices, both emulated and physical... am I doing something wrong? Thanks!

  • `Saving a photo taking a very long time` Clearly a wrong subject. Saving does not take long you confirmed. Appearing in Galley takes long. Quite diffrent. – blackapps Nov 13 '19 at 08:58
  • `To move the attachment,` Which attachment? Is there an attachment? What has it to do with the picture taken? And why would you move it? – blackapps Nov 13 '19 at 08:59
  • Further: The MediaStore needs time to discover new files. Now and the it does a rescan on its own. You wait for that. But you can also invoke the media scanner to index your file right away. – blackapps Nov 13 '19 at 09:04

1 Answers1

1

This was caused by Android's Media Scanner not immediately realizing new files existed.

From this Git issue and the subsequent PR: https://github.com/itinance/react-native-fs/issues/79

I modified my code as follows:

  saveImage = async filePath => {
    try {
      // set new image name and filepath
      const newImageName = `${moment().format("DDMMYY_HHmmSSS")}.jpg`;
      const newFilepath = `${dirPicutures}/${newImageName}`;
      // move and save image to new filepath
      const imageMoved = await this.moveAttachment(filePath, newFilepath).then(
        imageMoved => {
          if (imageMoved) {
            return RNFS.scanFile(newFilepath);
          } else {
            return false;
          }
        }
      );
      console.log("image moved", imageMoved);
    } catch (error) {
      console.log(error);
    }
  };

using RNFS's scanFile method to force the Media Scanner to realize the file exists. This is rough code I'll need to clean up, but it gets the job done.