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 344 forks source link

In android it does nothing and not showing any error logs. Works fine in iOS #529

Open kuldipopenxcell opened 3 months ago

kuldipopenxcell commented 3 months ago

bug report

In react native latest version (0.73.6) snapshot is not capturing in Android device. It works fine in IOS.

Version & Platform

npm ls react-native react-native-view-shot #
├─┬ @react-native-async-storage/async-storage@1.23.1
│ └── react-native@0.73.6 deduped
├─┬ @react-native-google-signin/google-signin@11.0.1
│ └── react-native@0.73.6 deduped
├─┬ @react-navigation/bottom-tabs@6.5.20
│ ├─┬ @react-navigation/elements@1.3.30
│ │ └── react-native@0.73.6 deduped
│ └── react-native@0.73.6 deduped
├─┬ @react-navigation/native-stack@6.9.26
│ └── react-native@0.73.6 deduped
├─┬ @react-navigation/native@6.1.17
│ └── react-native@0.73.6 deduped
├─┬ agora-react-native-rtm@1.5.1
│ └── react-native@0.73.6 deduped
├─┬ agora-rn-uikit@5.0.2
│ └── react-native@0.73.6 deduped
├─┬ react-native-agora@4.3.0-build.1 invalid: "^4.1.0" from node_modules/agora-rn-uikit
│ └── react-native@0.73.6 deduped
├─┬ react-native-element-dropdown@2.10.4
│ └── react-native@0.73.6 deduped
├─┬ react-native-fbsdk-next@12.1.4
│ └── react-native@0.73.6 deduped
├─┬ react-native-image-picker@7.1.2
│ └── react-native@0.73.6 deduped
├─┬ react-native-iphone-x-helper@1.3.1
│ └── react-native@0.73.6 deduped
├─┬ react-native-keyboard-aware-scroll-view@0.9.5
│ └── react-native@0.73.6 deduped
├─┬ react-native-linear-gradient@3.0.0-alpha.1
│ └── react-native@0.73.6 deduped
├─┬ react-native-maps@1.14.0
│ └── react-native@0.73.6 deduped
├─┬ react-native-modal-datetime-picker@17.1.0
│ └── react-native@0.73.6 deduped
├─┬ react-native-modal@13.0.1
│ └── react-native@0.73.6 deduped
├─┬ react-native-responsive-screen@1.4.2
│ └── react-native@0.73.6 deduped
├─┬ react-native-safe-area-context@4.9.0
│ └── react-native@0.73.6 deduped
├─┬ react-native-screens@3.30.1
│ └── react-native@0.73.6 deduped
├─┬ react-native-simple-toast@3.3.1
│ └── react-native@0.73.6 deduped
├─┬ react-native-splash-screen@3.3.0
│ └── react-native@0.73.6 deduped
├─┬ react-native-view-shot@3.8.0
│ └── react-native@0.73.6 deduped
├─┬ react-native@0.73.6
│ └─┬ @react-native/virtualized-lists@0.73.4
│   └── react-native@0.73.6 deduped
├─┬ react-redux@9.1.0
│ └── react-native@0.73.6 deduped
└─┬ toggle-switch-react-native@3.3.0
  └── react-native@0.73.6 deduped

Platform: Android

Expected behavior

It should return with URI of the image

Actual behavior

It returns nothing

Sample Code


const MapPage = () => {
  const mapRef = useRef();
  const viewRef = useRef();
  const captureMap = async () => {
    try {
      // Capture map as image
      const uri = await viewRef.current.capture();
      console.log('uri', uri);
    } catch (error) {
      console.error('Error:', error);
      Alert.alert('Error', 'Failed to save PDF.');
    }
  };

  return(
    <View style={styles.container}>
          <ViewShot ref={viewRef} style={{flex: 1}}>
            <MapView
              ref={mapRef}
              style={{flex: 1}}
              scrollEnabled={false}
              provider={PROVIDER_GOOGLE}
              initialRegion={{
                latitude: 55.8622166,
                longitude: 12.388021,
                latitudeDelta: 0.0922,
                longitudeDelta: 0.0421,
              }}
              onTouchStart={handleTouchStart}
              onPanDrag={handlePanDrag}
              onTouchEnd={handleTouchEnd}>
              {lines.map((line, index) => (
                <Polyline
                  key={index}
                  coordinates={line}
                  strokeColor="#FF0000"
                  strokeWidth={3}
                />
              ))}
            </MapView>
          </ViewShot>
          <Button label="Capture screenshot" onPress={captureMap} />
        </View>
    )
}
devethan commented 3 months ago

In my case, always stuck in these code only in Android

      const uri = await viewRef.current.capture();

there's no error, just still going on. But iOS is working fine.

kuldipopenxcell commented 3 months ago

I tried with this code also but there is no error logs and no clue to fix this.

  const captureSnapshot = async () => {
    try {
      const uri = await captureRef(viewRef, {
        format: 'png', // You can change the format if needed
        quality: 1, // Quality of the image, from 0 to 1
      });

      // Do something with the captured image URI (e.g., save it to disk or display it)
      console.log('Snapshot URI:', uri);
    } catch (error) {
      console.error('Error capturing snapshot:', error);
    }
  };
adaerodriguez commented 3 months ago

Hi guys, any advance with this issue? I have the same problem with react-native 0.73.6, on ios works great, but with Android, nothing happens

Thanks!!

kuldipopenxcell commented 3 months ago

Hi guys, I have found the alternative for this. since this is not working well for Android. Here you can use React Native Skia: Snapshot Views | React Native

connor-wj-kang commented 2 months ago

Hi guys. The same problem here. But I came up with a workaround. Just capture the full screen. After that you can clip the full screen image to the shape whatever you want.

import { captureScreen } from "react-native-view-shot";

captureScreen({
  format: "jpg",
  quality: 0.8,
}).then(
  (uri) => console.log("Image saved to", uri),
  (error) => console.error("Oops, snapshot failed", error)
);
jordanwegener commented 3 weeks ago

Hi guys. The same problem here. But I came up with a workaround. Just capture the full screen. After that you can clip the full screen image to the shape whatever you want.

import { captureScreen } from "react-native-view-shot";

captureScreen({
  format: "jpg",
  quality: 0.8,
}).then(
  (uri) => console.log("Image saved to", uri),
  (error) => console.error("Oops, snapshot failed", error)
);

Tried this and still not working for me, still no file saved/blank when shared.

nicodbsn commented 2 weeks ago

Hi guys, I ran into the same issue as OP and found a workaround by switching from core API RN Share to react-native-share.

Keep using the ViewShot config but replace your capture function with this :

const onCapture = async () => {
    const uri = await captureRef(ref, {
      format: 'png',
      quality: 0.9,
    });

    await Share.open({url: uri});
};

For whatever reason, the core Share API seems to expose url param only for iOS, that is what should cause the issue on Android.

YogeshwarSharma commented 2 weeks ago

Resolve this in Android using React Native Patch Packages.

kbqdev commented 1 day ago

@YogeshwarSharma Still not working.

YogeshwarSharma commented 1 day ago

Hope, You have used patch-package and applied react-native-view-shot+3.8.0.patch

kbqdev commented 1 day ago

Yes, i did. But mapview still missing. I try set collapsable to false/true but same result.

kbqdev commented 1 day ago

This is my captureOptions const options ={ format: 'png', quality: 1, result: 'tmpfile', snapshotContentContainer: false, handleGLSurfaceViewOnAndroid: true, useRenderInContext: false,} When i set handleGLSurfaceViewOnAndroid to true Mapview will appear but other view will not and handleGLSurfaceViewOnAndroid to false. Mapview will disappear.