[안드로이드] 저장소 사용하기 - 2. Scoped Storage

2021. 2. 24. 10:45바삭바삭 IT/안드로이드

안드로이드 버전10 이상부터는 Scoped Storage를 사용합니다. 이전 버전이였던 Legacy Storage와 어떤차이가 있는걸까요? 지난 포스트에서도 말했듯이 안드로이드의 저장소는 크게 내부저장소와 외부저장소로 나뉩니다. 두 버전에서 내부저장소는 동일하고 외부저장소의 구조가 살짝 바뀌었습니다. 

 

외부저장소 구조의 변화

기존에는 공용공간안에 모든 파일이 저장되었다면, 변경된 후에는 개별공간이 샌드박스 형태로 보호되어있고 공용공간 또한 타입별로 분리되었습니다. 개별 앱 공간은 앱 삭제시 함께 제거되고, 공용공간은 앱이 삭제되어도 기기에 남아있습니다.


외부저장소 접근 방법

1. 개별 앱 접근방법

개별 앱 공간은 따로 권한요청이 필요 없고 Context.getExternalFilesDir()를 통해 자신의 앱 공간에만 접근할 수 있습니다. 기존에는 EXTERNAL_STORAGE권한으로 다른 앱의 개별공간을 접근했지만 변경된 후 부터는 접근할 수 없습니다.

 

2. 공용공간 접근방법 (Media부분 - 사진 및 동영상, 음악)

안드로이드 버전 10부터는 MediaStore api 사용을 권장하고 있습니다. MediaStore은 사용자가 가지고있는 파일들을 다른 앱에서도 사용될 수 있도록 설계된 api입니다. Media디렉토리 안에서는 자신의 앱에 해당하는 곳은 권한없이 사용할 수 있습니다. 이전 버전에서는 WRITE_EXTERNAL_STORAGE만 있으면 다른 앱의 공용파일에도 접근할 수 있었지만, 보안상의 이슈로 10부터는 이를 막아놓은 것입니다.

 

아래 코드는 MediaStore API 샘플입니다. 만약, 다른 앱의 미디어스토어를 사용하려면 접근권한이 필요합니다.

val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI

val projection = arrayOf(MediaStore.Images.Media._ID,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATE_TAKEN)

val sortOrder = MediaStore.Images.Media.DATE_TAKEN + " DESC"

context.contentResolver.query(
uri, //찾고자 하는 데이터의 Uri
projection, //DB의 column과 같다
null, //Selection, DB의 where과 같다
null, //Selection args, selection에서 물음표에 들어갈 값
sortOder //쿼리 결과데이터의 정렬 기준
)?.use{ cursor ->
	while(cursor.moveToNext()){
    	//projection의 ID column을 사용해서 미디어 아이템의 URI획득
    }
}

 

3. 공용공간 접근방법 (Downloads부분 - 기타 파일들)

미디어 파일 외의 파일들에 접근하는 방법입니다. 이곳은 접근권한 없이 Storage Access Framework와 시스팀 파일 선택기를 통해 사용자가 명시적으로 파일을 선택할 수 있습니다. 

 

Stroage Access Framework는 선택 ui를 화면에 띄워서 앱에서 파일에 접근할 수 있도록 합니다. Intent.ACTION_OPEN_DOCUMENT액션을 사용해 새로운 액티비티를 띄우는 방식입니다.

val READ_REQUEST_CODE : Int = 42

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply{	
	addCategory(Intent.CATEGORY_OPENABLE)	//열 수 있는 파일들만 보고싶을 때 사용
    type = "image/*"	//타입과 일치하는 파일들만 보여줍니다.
}

startActivityForResult(intent, READ_REQUEST_CODE)

선택ui에서 이미지 하나를 선택하면 해당 이미지의 Uri가 앱으로 전달됩니다.

override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
    super.onActivityResult(requestCode, resultCode, resultData)

    if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
        resultData?.data?.also { uri ->
            showImage(uri)
        }
    }
}

 


저장소 사용방법 요악

파일위치 권한 접근 앱 삭제시 제거
내부저장소 개별 앱 공간 필요 없음 Context.getFilesDir() Y
외부저장소 개별 앱 공간 필요 없음 Context.getExternalFilesDir() Y
공용공간 Media(사진 및 동영상, 음악) READ_EXTERNAL_STORAGE (다른 앱 접근할때만) MediaStore(or SAF) N
Downloads(기타) 필요없음 Storage Access Framework(system's file picker) N

 


 

출처

codechacha.com/ko/android-storage-access-framework/

 

안드로이드 - SAF(Storage Access Framework)로 파일 읽고 쓰는 방법

SAF(Storage Access Framework)는 문서 및 이미지 등 각종 파일을 탐색하고 저장하는 작업을 간편하게 하려고 도입하였습니다. 앱은 ACTION_OPEN_DOCUMENT, ACTION_CREATE_DOCUMENT 등의 인텐트로 파일을 읽고 쓸 수

codechacha.com

simsimjae.tistory.com/267

 

외장메모리공간

안드로이드의 외장 공간이란? public static File getExternalStorageDirectory() 이 함수는 외장 메모리 디렉토리를 리턴한다. 다른 컴퓨터에 의해서 외장 메모리가 연결되었거나, 디바이스로부터 외장 메모

simsimjae.tistory.com

 

반응형