未だに何回実装しても覚えられないし、毎回調べてるので使う部分のコードだけメモ
(なんか説明がごちゃごちゃしすぎじゃない?)
細かいAPIの説明はネットに十分にあるので割愛。
コードは画像例(動画などの場合はMIME_TYPEやMediaURIなどを合わせて実装)
エラーハンドリングは各自でお願いします。
パターン1 ByteArrayで書き込む
SaveMedia.kt
private fun savedImageMediaStoreFile(imageUri: Uri, data: ByteArray, fileName: String){
val collection = if (Build.VERSION.SDK_INT >= 29) {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
val contentValues = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
put(MediaStore.Images.Media.MIME_TYPE, "image/png")
if (Build.VERSION.SDK_INT >= 29) {
put(MediaStore.Images.Media.IS_PENDING, true)
}
// //※1 専用直下フォルダを作成したい場合
// put(
// MediaStore.Images.ImageColumns.RELATIVE_PATH,
// Environment.DIRECTORY_PICTURES + "/MY_DIRECTORY/"
// )
}
val contentResolver = applicationContext.contentResolver
val contentUri = contentResolver.insert(collection, contentValues)
//※2 ファイルを書き込む
contentResolver.openFileDescriptor(contentUri!!, "w", null).use {
FileOutputStream(it!!.fileDescriptor).use { output ->
output.write(data)
}
}
contentValues.clear()
if (Build.VERSION.SDK_INT >= 29) {
contentResolver.update(contentUri, contentValues.apply {
put(MediaStore.Images.Media.IS_PENDING, false)
}, null, null)
} else {
contentResolver.update(contentUri, contentValues, null, null)
}
}
※1
自分で指定したフォルダを作成して、その直下に保存してくれます。
ない場合はPictures/xxxxxx.pngだが、
/MY_DIRECTORY/を指定することによってPictures/MY_DIRECTORY/xxxxxx.png
に保存してくれる。
Uriで書き込む
SaveMedia.kt
//※2の部分のみ
contentResolver.openInputStream(imageUri).use { input ->
val output = contentResolver.openOutputStream(contentUri, "w")!!
input!!.copyTo(output)
}
感想
byteArrayで書き込むサンプルとUriで書き込むサンプルが混同してるので余計混乱していたように感じる。