Save image to media picture on Android
- link
- Android
val GALLERY_PATH = "${Environment.DIRECTORY_PICTURES}/lab"
fun saveToPictures(src: Uri, title: String) {
save(src, title, "png", GALLERY_PATH)
}
fun saveToDownloads(src: Uri, name: String) {
save(
src,
name.substringBeforeLast("."),
name.substringAfterLast("."),
Environment.DIRECTORY_DOWNLOADS
)
}
private fun save(src: Uri, title: String, ext: String, relativeParent: String) {
val name = "${title.chunked64().withTimestamp}.$ext"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val destRoot = when (relativeParent) {
GALLERY_PATH -> MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
else -> MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
}
saveToMediaStore(src, destRoot, name, relativeParent)
} else {
saveToExternalStorage(src, "${relativeParent}/$name")
}
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun saveToMediaStore(src: Uri, destRoot: Uri, name: String, relativeParent: String) {
ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.RELATIVE_PATH, relativeParent)
put(MediaStore.MediaColumns.IS_PENDING, 1)
if (name.endsWith("png")) {
put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
}
contentResolver.insert(destRoot, this)?.let {
src.copyTo(it)
clear()
put(MediaStore.MediaColumns.IS_PENDING, 0)
contentResolver.update(it, this, null, null)
}
}
}
private fun saveToExternalStorage(from: Uri, relativePath: String) {
File(Environment.getExternalStorageDirectory(), relativePath).apply {
parentFile?.mkdirs()
createNewFile()
from.copyTo(this.toUri())
}
}
val String.withTimestamp: String
get() {
val suffix = SimpleDateFormat("yyMMddHHmmss", Locale.ENGLISH)
.format(Date())
// 12 is suffix's length
val suffixPattern = Regex(".*-[\\d]{12}$")
val nameWithoutSuffix = if (suffixPattern.matches(this)) {
this.substringBeforeLast("-")
} else {
this
}
return "$nameWithoutSuffix-$suffix"
}
fun String.chunked64() = chunked(64).firstOrNull() ?: UUID.randomUUID().toString()