android/code
[android]Scoped Storage
pearlab
2023. 12. 13. 16:21
Legacy External Storage(OLD)
targetSdk API Level 29 이하
WRITE_EXTERNAL_STORAGE 권한이
구분 없이 외부저장소부터 대부분의 공간에 접근하고 쓰기가 가능했습니다.
val file = File(Environment.getExternalStorageDirectory(), "test.txt")
Scoped Storage(NEW)
targetSdk API Level 30이상
Media 유형
다른앱과 공유되는 영역의 미디어 파일은 모두 MediaStore를 이용하여 생성해야 합니다.
// Scoped Storage
val resolver = applicationContext.contentResolver
val audio = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val record = ContentValues().apply {
put(MediaStore.Audio.Media.DISPLAY_NAME, "record.wav")
}
val uri = resolver.insert(audio, record)
content://media/external/audio/media/{id}
Storage Access Framework Example
GUI Action 없이 불가능
ACTION_CREATE_DOCUMENT, ACTION_OPEN_DOCUMENT, ACTION_OPEN_DOCUMENT_TREE 인텐트 작업을 호출하고 문서 제공자에서 반환한 파일을 수신합니다.
val resolver = applicationContext.contentResolver
private val myCode: Int = 1000
private fun reqeustCreateDoc() {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
putExtra(Intent.EXTRA_TITLE, "example.txt")
type = "application/txt"
}
startActivityForResult(intent, myCode)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == myCode && resultCode == Activity.RESULT_OK && data != null) {
Thread {
val inUri = Uri.parse(".../text.txt")
val outUri = (data.data) as Uri
download(inUri, outUri)
}.start()
}
}
private fun download(sourceUri: Uri, destUri: Uri) {
val connect = URL(sourceUri.toString()).openConnection()
val inputStream = connect.getInputStream()
val outputStream: FileOutputStream = contentResolver.openFileDescriptor(destUri, "w")?.use { pfd ->
FileOutputStream(pfd.fileDescriptor)
} ?: throw IllegalArgumentException()
//[Todo]write
}