일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 웹뷰
- image
- 유튜브
- coroutine
- studio
- 레트로핏
- Kotlin
- build
- 안드로이드
- Android
- error
- 의존성주입
- Gradle
- MVVM
- Github
- 안스
- WebView
- dart
- 안드로이드 스튜디오
- Retrofit
- 코틀린
- ADB
- viewpager
- 스튜디오
- 에러
- 깃헙
- 안드로이드스튜디오
- RecyclerView
- 코루틴
- GIT
- Today
- Total
코딩하는 일용직 노동자
Android 10(Q) Scope Storage 에 관하여 본문
Android 10(Q) 부터는 기존의 저장공간과는 다른 개념으로 바뀌었습니다.
10 이전의 안드로이드는 기본적으로 내부저장공간과 외부저장공간으로 나뉩니다.
# Android 10(Q) 이전의 Storage
내부저장공간은 샌드박스 형식으로 보호되는 공간을 할당받습니다.
ex) com.kakao.talk, com.kakao.story, com.app.a
그리고 각 앱은 자신의 저장공간만 접근하고 사용할 수 있습니다.
10 에서도 내부저장공간은 마찬가지로 사용됩니다.
반면 외부저장공간은 하나의 큰 공통저장공간으로 운영되었습니다.
READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE 권한만 있으면
어떤앱이 작성한 파일이든, 어느 경로에 있든, 어떤 파일이든 모두 접근/수정할 수 있었습니다.
EXTERNAL_STORAGE 권한은 안드로이드 앱에서 가장 많이 사용되는 권한입니다.
이 권한의 남용으로 그동안 많은 문제들이 발생했습니다.
파일들이 어떤 앱에서 사용되는지 명확하지 않아 관리가 어렵고,
앱을 제거한 후에도 많은 파일 sdcard 에 남아 저장공간을 차지했습니다.
또한 다른 앱에서 잠재적으로 민감한 파일을 읽을 수도 있습니다.
# Android 10(Q) 를 적용하기 싫다면
만약 자신의 앱에 Scoped Storage를 바로 적용할 준비가 안된 개발자들을 위해, 구글은 이전 방식을 사용할 수 있도록 유예기간을 두었습니다.
앱이 Android 10 기기에서 Scoped storage 정책을 적용받지 않으려면 다음 중 1가지 방법을 적용해야 합니다.
방법1. Target SDK를 안드로이드 API 28 이하로 설정
방법2. Target SDK를 안드로이드 API 29 이상으로 설정하는 경우, 매니페스트파일 requestLegacyExternalStorage 속성을 true로 설정
<manifest ... >
<!-- This attribute is "false" by default on apps targeting Android Q. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
# Android 10(Q) 부터의 Storage
이제 앱에서는 더이상 sdcard/ 이하의 영역에 직접 접근할 수 없습니다.
외부저장공간의 경로를 얻기위해 많이 사용하던 Environment.getExternalStorageDirectory()는 deprecated 되었습니다.
Android 10에서는 기존 외부저장공간의 public 한 개념이 사라집니다.
공용공간으로 다운로드, 사진 및 영상, 음악 공간이 있고, 샌드박스 형식의 개별앱공간으로 나뉘어서 관리됩니다.
getExternalFilesDir() 이나 getExternalCacheDir() 을 사용하면
/Android/data/패키지명/files
/Android/data/패키지명/cache
폴더가 자동으로 생성되며 READ_EXTERNAL_STORAGE 퍼미션을 별도로 획득하지 않아도 파일의 접근이 가능합니다.
외부저장공간의 개별앱공간은 내부저장공간과 비슷한 형식으로 동작합니다.
이제 추가권한없이 개별앱공간을 읽고 쓸 수 있습니다.
개별앱공간은 샌드박스 형식으로 관리되며 다른 앱의 공간으로는 접근할 수 없습니다.
외부저장공간의 공용공간은 다운로드, 사진및영상, 음악 공간이 있고 각 공용공간은 MediaStore를 통해 읽고 쓸 수 있습니다.
다운로드 공간을 제외한 나머지 공간은 해당 타입에 맞는 파일만 저장할 수 있습니다.
추가권한없이 각 공용공간에 파일을 생성할 수 있고, 자신이 생성한 파일을 읽을 수 있습니다.
앱이 삭제되면 해당앱이 가지고 있던 모든 파일이 삭제됩니다.
만약 앱 삭제 후에도 파일을 보존할 필요가 있다면 MediaStore를 통해 파일을 생성한 후 메타데이터를 추가해야 합니다.
자신이 생성한 파일에 대해서는 읽기/쓰기 권한이 필요없지만, 공용공간에 저장된 다른앱이 생성한 파일에 대해서는 권한이 필요합니다.
이를 위해 Android 10에서는 READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO 권한이 새롭게 추가되었습니다.
각 앱은 다른앱이 다운로드 공간에 생성한 파일을 직접 접근할 수 없습니다.
앱이 Android 10의 다른 앱에서 만든 비 미디어 파일에 액세스하는 유일한 방법은 Storage Access Framework 에서 제공하는 파일 선택기를 사용하는 것입니다.
(https://developer.android.com/guide/topics/providers/document-provider#kotlin)
Storage Access Framework 를 이용한 파일 검색 방법은 아래처럼 사용하면 됩니다.
private val REQUEST_CODE_FOR_SINGLE_FILE: Int = 3020
...
fun findImageFiles() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
// Filter to only show results that can be "opened", such as a
// file (as opposed to a list of contacts or timezones)
addCategory(Intent.CATEGORY_OPENABLE)
// Filter to show only images, using the image MIME data type.
// If one wanted to search for ogg vorbis files, the type would be "audio/ogg".
// To search for all documents available via installed storage providers,
// it would be "*/*".
type = "image/*"
}
startActivityForResult(intent, REQUEST_CODE_FOR_SINGLE_FILE)
}
private val EDIT_REQUEST_CODE: Int = 3030
...
fun findPdfFiles() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
// Filter to only show results that can be "opened", such as a
// file (as opposed to a list of contacts or timezones)
addCategory(Intent.CATEGORY_OPENABLE)
// Filter to show only images, using the image MIME data type.
// If one wanted to search for ogg vorbis files, the type would be "audio/ogg".
// To search for all documents available via installed storage providers,
// it would be "*/*".
// type = "text/plain"
type = "application/pdf"
}
startActivityForResult(intent, EDIT_REQUEST_CODE)
}
# 정리하며...
그동안 외부저장장치에 파일을 읽고 쓰는것에는 큰 제약이 없었습니다.
사용자에게 READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE 권한만 획득하면 됐습니다.
그러다보니 외부저장장치에 여러 앱의 폴더가 무분별하게 생성되고 관리되었습니다.
앞으로는 딱 정해진 방식대로만 쓰라는 것이 이번 변경점의 특징이라고 할 수 있습니다.
자신이 개발하는 앱에서만 사용될 파일들은 getExternalFilesDir() 이나 getExternalCacheDir() 을 사용해 private 한 공간에서만 관리되도록 했습니다.
이 공간에 파일을 저장/수정/삭제 할때는 READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE 권한이 필요없습니다.
그리고 다운로드 폴더를 제외한 나머지 공간에서는 해당 타입에 맞는 파일(Image, Video, Audio)만 저장하도록 하고 MediaStore를 통해 저장/수정/삭제 되도록 했습니다.
이런 공통공간에 다른앱이 저장시켜 놓은 파일에 접근할때는 READ_EXTERNAL_STORAGE 권한을 요청하도록 합니다.
외부저장장치에 저장되어있는 파일들을 선택할때는 Storage Access Framework에서 제공하는 파일 선택기를 이용하도록 합니다.
안드로이드의 버전이 높아질수록 보안에 관한 내용이 꾸준히 추가되네요. -_-;;
'안드로이드' 카테고리의 다른 글
유튜브를 웹뷰로 구성하기 (1) (0) | 2020.05.11 |
---|---|
웹뷰 키보드 이슈 해결사례 (0) | 2020.05.07 |
코틀린 ScopeFunction 종류와 역할 (0) | 2020.05.03 |
File Exploler 라이브러리 (0) | 2020.05.03 |
Wifi ADB 디버깅 방법 (0) | 2020.05.03 |