목적: 앱 내 화면을 그대로 이미지로 추출하여 카카오톡이나 인스타로 공유 및 갤러리에 저장을 하고 싶음
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. 설치
=> 오토링크!
=> 오토링크!
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 에러가 났다.
그래서 또 구글링 해보니 해결책은 간단했다.
compileSdkVersion이 28이라 에러가 나는듯 했다.
그래서 아래처럼 모두 29로 설정해주니 해결되었다.
// android/build.gradle
compileSdkVersion = 29
targetSdkVersion = 29
참고 블로그
https://www.gkmit.co/blog/mobile-development/capture-and-share-screenshot-in-react-native
Buy Me A Coffee!
https://www.buymeacoffee.com/daheeahn
'Development > React Native' 카테고리의 다른 글
[React Native] Sentry로 로그 이벤트 확인하기 (1) | 2020.09.01 |
---|---|
[React Native] Deep Link 딥링크 (0) | 2020.08.24 |
[React Native] 테스트앱 관리자앱 만들기 (개인메모용) (0) | 2020.08.15 |
[React Native / Android] react-native-push-notification 진동/무음모드 시 알람 울리기 (Silent Mode) (11) | 2020.08.10 |
[React Native] react-native-push-notification: Android에서 custom sound가 안울림 / android userInfo 오류 (0) | 2020.07.14 |