Development/React Native

[React Native] 앱 화면 캡쳐 후 공유 및 갤러리에 저장하기 (Capture ScreenShot and Share)

안다희 2020. 8. 18. 22:15
728x90

목적: 앱 내 화면을 그대로 이미지로 추출하여 카카오톡이나 인스타로 공유 및 갤러리에 저장을 하고 싶음

 

1. 환경

react-native: 0.61.5

react-native-view-shot: 3.1.2

react-native-share: 3.7.0

@react-native-community/cameraroll: 4.0.0

2. 설치

1) react-native-view-shot

=> 오토링크!

 

2) react-native-share

=> 오토링크!

 

3) @react-native-community/cameraroll

=> 오토링크!

(https://coding-dahee.tistory.com/147 이곳에서 cameraroll 설치 방법 자세히 보기!)

 

https://coding-dahee.tistory.com/147

3. Usage

일단 캡쳐하고 싶은 부분을 ViewShot으로 감싸준다.

그리고 어떠한 버튼을 눌러서 캡쳐를 할 것이므로 아래와 같이 코드를 작성해준다.

import React, { useRef } from 'react';
import { SafeAreaView, Button, PermissionsAndroid, Platform } from 'react-native';
import ViewShot from 'react-native-view-shot';
import Share from 'react-native-share';
import CameraRoll from '@react-native-community/cameraroll';

import { ShareBox } from './styled';

export default () => {
  const captureRef = useRef();

  const getPhotoUri = async (): Promise<string> => {
    const uri = await captureRef.current.capture();
    console.log('👂👂 Image saved to', uri);
    return uri;
  };

  const onCapture = async (social: Share.Social) => {
    try {
      const uri = await getPhotoUri();

      const options = {
        title: 'Share Title',
        message: 'Share Message',
        url: uri,
        type: 'image/jpeg',
      };

      if (social === null) {
        const result = await Share.open(options);
        console.log('😻😻 result with no social', result);
      } else {
        const result = await Share.shareSingle({
          ...options,
          social,
        });
        console.log(`😻😻 result with social ${social}`, result);
      }
    } catch (e) {
      console.log('😻😻😻 snapshot failed', e);
    }
  };

  const hasAndroidPermission = async () => {
    const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;

    const hasPermission = await PermissionsAndroid.check(permission);
    if (hasPermission) {
      return true;
    }

    const status = await PermissionsAndroid.request(permission);
    return status === 'granted';
  };

  const onSave = async () => {
    if (Platform.OS === 'android' && !(await hasAndroidPermission())) {
      toast('갤러리 접근 권한이 없어요');
      return;
    }

    const uri = await getPhotoUri();
    const result = await CameraRoll.save(uri);
    console.log('🐤result', result);
  };

  return (
    <SafeAreaView>
      <ViewShot ref={captureRef} options={{ format: 'jpg', quality: 0.9 }}>
        <ShareBox>
          <SSubColorText>이 박스가 캡쳐됩니다</SSubColorText>
        </ShareBox>
      </ViewShot>

      <Button title="공유" onPress={() => onCapture(null)} />
      <Button title="인스타 공유" onPress={() => onCapture(Share.Social.INSTAGRAM)} />
      <Button title="갤러리에 저장" onPress={onSave} />
    </SafeAreaView>
  );
};

(ShareBox는 내가 만든 styled-components)

 

아주 유용한 코드!!

 

** 캡쳐하는 부분의 backgroundColor를 지정해주지 않으면 캡쳐 후 이미지가 검은색으로 보이니까 당황하지 말기!

 

 

 

 

3-1. 에러

iOS에서는 save 함수가 문제 없다. 하지만 안드로이드에서는 save 함수를 사용하니 권한이 허용되어 있음에도 불구하고 Permission denied 에러 로그가 뜨면서 사진 저장이 되지 않았다.

 

github.com/react-native-community/react-native-cameraroll/issues/192#issuecomment-648866758

같은 이슈를 겪고 있는 사람이 많았다.

 

나의 설정은 이러했다.

// android/build.gradle

        compileSdkVersion = 28
        targetSdkVersion = 29

 

targetSdkVersion가 29 이상이면 추가 설정을 해줘야 하나보다. 위 링크 설명처럼

https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage

manifest 파일에

<application android:requestLegacyExternalStorage="true" ... >

를 추가해줬다.

 

 

3-2. 에러

그러자 error: attribute android:requestLegacyExternalStorage not found 에러가 났다.

그래서 또 구글링 해보니 해결책은 간단했다.

https://stackoverflow.com/questions/58976425/aapt-error-attribute-androidrequestlegacyexternalstorage-not-found

 

compileSdkVersion이 28이라 에러가 나는듯 했다.

 

그래서 아래처럼  모두 29로 설정해주니 해결되었다.

// android/build.gradle

        compileSdkVersion = 29
        targetSdkVersion = 29

 

 

 

 

 

참고 블로그

https://www.gkmit.co/blog/mobile-development/capture-and-share-screenshot-in-react-native

 

Capture and Share screenshot in react native

let’s learn how to take a screenshot in react native and share it.

www.gkmit.co

 

 

 

Buy Me A Coffee!

https://www.buymeacoffee.com/daheeahn

 

daheeahn is app developer

Hey 👋 I just created a page here. You can now buy me a coffee!

www.buymeacoffee.com

 

 

 

출처: https://mingos-habitat.tistory.com/34 [밍고의서식지:티스토리]