[Android] Storage Access Framework(SAF) 이란?

WonseokOh·2022년 5월 6일
0

Android

목록 보기
9/16
post-thumbnail

Storage Access Framework(SAF)

  Android 4.4(API 19)이후부터 문서, 이미지(사진) 및 각종 다른 파일을 탐색하고 여는 작업을 간편하게 해주는 Storage Access Framework(SAF)가 도입이 되었습니다. Selector를 통해 사용자가 일관된 방식으로 파일을 탐색하고 최근 기록에 액세스 할 수 있습니다.


SAF 구성 요소

DocumentProvider

문서를 제공하는 주체로 DocumentProvider 클래스를 상속받고 있으며 Android 기본적으로 내장된 다운로드, 이미지, 동영상과 같은 앱들이 DoucmnetProvider 클래스를 상속받아 문서들을 제공해줍니다.

Client App

DocumentProvider에서 제공된 문서, 파일들을 사용하는 클라이언트 앱

Selector

일종의 시스템 UI로 사용자가 필요한 파일을 선택할 때 사용되는 UI입니다.


SAF의 특징

  • SAF는 문서를 제공하는 Provider와 제공된 문서들을 사용하는 Client 구조로 나뉘게 됩니다.
  • 서드파티 앱이 문서를 제공하는 Provider 역할을 함과 동시에 다른 Provider를 사용하는 Client 역할을 할 수도 있습니다.
  • 사용자는 Selector를 통해서 하나의 앱이 아닌 모든 Document Provider로부터 문서, 파일들을 찾을 수 있습니다.
  • 클라이언트 앱은 DocumentProvider에서 제공한 문서에 액세스 권한을 가지며 사용자가 제공자의 파일을 추가, 삭제, 변경 및 저장을 할 수 있습니다.
  • USB가 연결이 되면 USB 저장소 Provider도 지원합니다.

SAF 흐름

  위의 그림은 사진 앱(com.example.photos) 에서 SAF를 사용하여 파일들을 액세스 할 수 있는 flow를 나타냅니다. PhotoViewer는 ACTION_OPEN_DOCUMENT를 사용하여 Selector에서 원하는 Provider를 선택한 후 파일을 읽습니다. PhotoEditor는 ACTION_CREATE_DOCUMENT를 사용하여 파일을 저장합니다.


클라이언트 앱 구현

private fun bindViews() = with(binding){
        actionPickButton.setOnClickListener {
            startActivityForResult(
                Intent(Intent.ACTION_PICK).apply {
                    type = "image/*"
                },
                READ_REQUEST_CODE
            )
        }

        actionGetContentButton.setOnClickListener {
            startActivityForResult(
                Intent(Intent.ACTION_GET_CONTENT).apply {
                    type = "image/*"
                },
                READ_REQUEST_CODE
            )
        }

        actionOpenDocumentButton.setOnClickListener {
            startActivityForResult(
                Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
                    type = "image/*"
                },
                READ_REQUEST_CODE
            )
        }

        actionOpenDocumentTreeButton.setOnClickListener {
            startActivityForResult(
                Intent(Intent.ACTION_OPEN_DOCUMENT_TREE),
                READ_REQUEST_CODE
            )
        }
    }

4개의 버튼을 두어 각 버튼별로 Intent Action을 다르게 설정하였습니다. Android 4.3 이하에서 앱이 다른 앱의 파일을 검색하기 위해서는 ACTION_PICK 또는 ACTION_GET_CONTENT와 같은 액션을 호출해야 합니다. 그 이후 사용자는 파일을 선택할 앱을 하나 선택합니다. ACTION_PICK과 ACTION_GET_CONTENT와는 차이점이 존재하는데 ACTION_PICK은 사진, 앨범에서만 파일을 가져오기에 모든 파일의 URI의 Authority는 동일하고 ID는 다르지만 ACTION_GET_CONTENT 사진, 앨범 이외의 구글 포토, Download Provider로부터도 파일을 가져올 수 있어 URI가 다양합니다


Android 4.4(API 19) 이상에서는 ACTION_OPEN_DOCUMENT 인텐트 액션을 사용하며 ACTION_GET_CONTENT와 매우 유사합니다. 구글 공식문서에서는 ACTION_OPEN_DOCUMENT가 ACTION_GET_CONTENT를 대체할 목적으로 만들어진 것이 아니며 어느 것을 사용할 지는 각 앱의 필요성에 따라 좌우됩니다.

  • ACTION_GET_CONTENT : 단순한 데이터 읽는데 적합, 이 방식 사용 시 데이터 사본을 가져옴
  • ACTION_OPEN_DOCUMENT : 데이터에 장기적, 지속적 액세스 권한을 가져야할 경우 사용
  • Android 5.0(API 21) 이상에서는 ACTION_OPEN_DOCUMENT_TREE 인텐트 액션을 사용할 수 있으며, 이 인텐트로 사용자는 앱에서 탐색하고자 하는 디렉터리를 지정하여 권한을 부여할 수 있습니다.

참고

  SAF를 사용하여 파일 읽는 방법만 서술하였지만, 그외에도 파일 생성, 수정, 삭제 등 SAF를 활용하는 방법이 있습니다. 아래 참고 블로그와 공식문서를 보시면 도움이 많이 될 것입니다. 😆

profile
"Effort never betrays"

0개의 댓글