gre / react-native-view-shot

Snapshot a React Native view and save it to an image
https://github.com/gre/react-native-view-shot-example
MIT License
2.64k stars 343 forks source link

On Android, captured image cannot be shared (empty share dialog) #538

Open jordanwegener opened 1 month ago

jordanwegener commented 1 month ago

Captured image cannot be shared on Android

After a capture, trying to share using the resultant URI results in an empty message which is rejected by the elected app to share to.

  const captureReceipt = async () => {
    if (!viewShotRef.current?.capture) {
      console.error('Failed to capture receipt: viewShotRef is not defined');
      return;
    }

    try {
      const uri = await captureRef(viewShotRef, {
        fileName: `payment-receipt-${new Date().toISOString()}`,
        format: 'png',
        quality: 0.9,
      });

      console.log(uri);
      Share.share({url: `file://${uri}`});
    } catch (error) {
      console.error('Failed to capture receipt', error);
    }
  };
file:///data/user/0/<censored-application-name>/cache/payment-receipt-2024-08-01T02%3A20%3A37.614Z839463387167296804.png

Version & Platform

"react-native-view-shot": "^3.8.0" "react-native": "0.74.1"

npm ls react-native react-native-view-shot
<censored-application-name>.../src
├─┬ @apolloeagle/loading-dots@3.0.0
│ └── react-native@0.74.1 deduped
├─┬ @okta/okta-react-native@2.12.0
│ └── react-native@0.74.1 deduped
├─┬ @react-native-async-storage/async-storage@1.23.1
│ └── react-native@0.74.1 deduped
├─┬ @react-native-firebase/app@19.3.0
│ └── react-native@0.74.1 deduped
├─┬ @react-navigation/bottom-tabs@6.5.20
│ ├─┬ @react-navigation/elements@1.3.30
│ │ └── react-native@0.74.1 deduped
│ └── react-native@0.74.1 deduped
├─┬ @react-navigation/native-stack@6.9.26
│ └── react-native@0.74.1 deduped
├─┬ @react-navigation/native@6.1.17
│ └── react-native@0.74.1 deduped
├─┬ @testing-library/jest-native@5.4.3
│ └── react-native@0.74.1 deduped
├─┬ @testing-library/react-native@12.5.0
│ └── react-native@0.74.1 deduped
├─┬ react-native-actions-sheet@0.9.3
│ └── react-native@0.74.1 deduped
├─┬ react-native-blob-util@0.19.9
│ └── react-native@0.74.1 deduped
├─┬ react-native-bootsplash@5.4.1
│ └── react-native@0.74.1 deduped
├─┬ react-native-device-info@10.13.2
│ └── react-native@0.74.1 deduped
├─┬ react-native-gesture-handler@2.16.2
│ └── react-native@0.74.1 deduped
├─┬ react-native-hyperlink@0.0.22
│ └── react-native@0.74.1 deduped
├─┬ react-native-linear-gradient@2.8.3
│ └── react-native@0.74.1 deduped
├─┬ react-native-localize@3.1.0
│ └── react-native@0.74.1 deduped
├─┬ react-native-paper@5.12.3
│ └── react-native@0.74.1 deduped
├─┬ react-native-pdf@6.7.5
│ └── react-native@0.74.1 deduped
├─┬ react-native-reanimated@3.11.0
│ └── react-native@0.74.1 deduped
├─┬ react-native-safe-area-context@4.10.1
│ └── react-native@0.74.1 deduped
├─┬ react-native-screens@3.31.1
│ └── react-native@0.74.1 deduped
├─┬ react-native-svg-transformer@1.3.0
│ └── react-native@0.74.1 deduped
├─┬ react-native-svg@15.2.0
│ └── react-native@0.74.1 deduped
├─┬ react-native-system-navigation-bar@2.6.4
│ └── react-native@0.74.1 deduped
├─┬ react-native-user-agent@2.3.1
│ └── react-native@0.74.1 deduped
├─┬ react-native-view-shot@3.8.0
│ └── react-native@0.74.1 deduped
├─┬ react-native-webview@13.8.7
│ └── react-native@0.74.1 deduped
└─┬ react-native@0.74.1 overridden
  └─┬ @react-native/virtualized-lists@0.74.83
    └── react-native@0.74.1 deduped

Platform: Android

Expected behavior

The image URI doesn't produce an empty message when shared.

Actual behavior

Share bottom sheet has no content, only contacts/apps:

image

If an app is selected:

image

Steps to reproduce the behavior

See code above

jordanwegener commented 1 month ago

Looked further into this and it seems that react native's Share and the Share provided by react-native-share are both unable to access the file created by ViewShot. After copying it out of the app's cache and into external storage using react-native-fs it can be shared from there.

import RNFS from 'react-native-fs';
import Share from 'react-native-share';
import {captureRef} from 'react-native-view-shot';

const filename = 'capture';

try {
  const uri = await captureRef(screenCaptureRef, {
    format,
    quality: 0.8,
  });
  const filePath = `${RNFS.DocumentDirectoryPath}/${filename}.${format}`;
  await RNFS.moveFile(uri, filePath);
  await Share.open({
    url: `file://${filePath}`,
    failOnCancel: false,
  });
} catch (error) {
  console.error('Error capturing viewshot:', error);
}

Not sure if this is specific to the app I'm working on or a broader issue with ongoing android compat. As it's not mentioned anywhere in docs (where sharing the resultant file is mentioned) I assume it's not the expected outcome so I'm inclined to leave this open until a maintainer can comment