티스토리 뷰

반응형

앱을 제작하다보니 앱의 현재 화면이나 화면의 일부 위젯을 이미지로 저장하기 

 

필요한 패키지는 아래와 같다. 

# 특정 위젯 screenshot 을 위한 패키지
screenshot: ^1.2.3
path_provider: ^2.0.11
permission_handler: ^9.2.0
image_gallery_saver: ^1.7.1
share_plus: ^4.0.9

screenshot 패키지는 flutter에서 원하는 widget tree 혹은 전체 UI를 캡쳐 할 수 있다. 

이때 캡쳐한 이미지를 저장하기 위해서 path_provider 패키지를 이용해서 저장할 directory를 쉽게 받아올 수 있다. 

permission_handler 는 이미지 저장시, 현재 프로젝트에 할당된 디렉토리 이외의 곳에 저장하려고 할 때 필요하다고 해서 추가했다. 

image_gallery_saver 는 이미지 파일을 안드로이드의 갤러리 폴더로 복사해주는 기능이 있어서 이용했다. 

share_plus는 생성한 파일을 다른 앱이나, 클라우드, 다른 기기에 이동시키려고 할 때 사용하면된다. 

 

 

screenshot 패키지의 사용법은 간단하다. (pubspec.yalm 파일의 dependency에는 당연히 추가해놓은 상태)

캡쳐할 위젯이 있는 파일에 import를 추가 한다. 

import 'package:screenshot/screenshot.dart';

 

그 위젯의 클래스에 아래와 같이 ScreenshotController 인스턴스를 만든다.

final ScreenshotController screenshotController = ScreenshotController();

나의 경우, 상태 관리 클래스가 따로 있어서 그곳에 생성했다. screenshot 패키지 페이지의 설명에는 globalKey를 이용해 위젯 key에 연결하여 ScreenController에 명령을 호출하는데, 내 코드에서는 자꾸 globalKeyInstance.currentState 가 null 이어서 get을 이용한 상태 관리 클래스에 집어 넣어 두고 호출했다. 

 

캡쳐를 원하는 위젯을 Screenshot 위젯으로 감싸고, controller 프로퍼티에 앞에서 생성한 screenshotController를 넣어준다.(아래 참고)

그리고 캡쳐를 실행할 기능을 만들어준다.

나의 경우, 버튼을 만들어서 onPressed 프로퍼티에 캡쳐 실행 코드를 입력

그러면 끝.

위의 코드에서

capture에 delay를 10 ms 준  이유는 https://pub.dev/packages/screenshot 의 마지막 부분에서 rendering 딜레이로 이전 프레임이 캡쳐되기도 한다며, 이를 위해 delay를 조금 주면된다는  것이었다. 나의 경우 이전 프레임을 가져와도 상관없긴하지만 일단 코드는 넣어놨다. 

그리고 'image.png'는 getApplicationDocumentsDirectory로 받아온 임의의 폴더에 저장된 이미지 파일의 파일명이고, 'firstScreenshot'은 갤러리에 복사된 이미지파일의 파일명이다

 

캡쳐를 하고 path_provider에서 제공하는 디렉토리에 저장을 하면, path_provider 에 있는 어떤 메소드를 사용하느냐에 따라 차이는 있겠지만, 

await getApplicationDocumentsDirectory();

 위와 같이 getApplicationDocumentDirectory를 사용할 경우, 프로젝트 디렉토리의 /app_fluuter/ 에 저장이 되고, 

await getExternalStorageDirectory();

getExternalStorageDirectory를 사용할 경우, 프로젝트 디렉토리의 /files/ 에 저장된다. (External 이라고 붙여진 이유는 앱에 할당된 저장소 밖에 있는 폴더이기 때문)

참고로 외부디렉토리(ExternalStorageDirectory)로 저장하려 할 경우, OS로부터 (권한문제 등으로) path를 받아오지 못할 수도 있어서 null이 될 수있으므로 아래 코드처럼 ?를 추가해줘야한다. 

final directory =
await getExternalStorageDirectory();
final imagePath =
    await File('${directory?.path}/image.png').create();

getExternalStorageDirectory() 로 받아온 path를 처리해서 안드로이드 디렉토리 중 내가 원하는 폴더에 넣거나 새로 생성해서 넣을 수도 있는 것 같다. 아래 링크의 글을 보면 그 방법을 사용하고 있다. 글의 중간쯤에  saveVideo function을 구현하는 코드의 7~19 line 을 참고. 

https://retroportalstudio.medium.com/saving-files-to-application-folder-and-gallery-in-flutter-e9be2ebee92a

 

Saving Files to Application Folder and Gallery in Flutter

The majority of Mobile Applications require some kind of file storage, where users can download or save files for future access…

retroportalstudio.medium.com

 

추가로, 

Android Studio에 있는 device file explorer를 이용해서 해당 폴더 보려고 하나면, getApplicationDocumentDirectory( ) 에서 받아온 디렉토리 path를 그대로 따라가면 안된다. 아래 와 같이 /data/user/0/ 까지의 부분을 /data/data/ 로 치환하여 그 경로로 찾아가면 확인 가능하다. (아래 캡쳐의 원문 링크)

 

또 찾은 정보. android에서 사용하는 경로에 대하여 정리된 자료 링크

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함