diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt index c8248281c0..d683eb0aac 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt @@ -1,12 +1,14 @@ package eu.kanade.tachiyomi.data.saver import android.annotation.SuppressLint +import android.content.ContentUris import android.content.Context import android.graphics.Bitmap import android.net.Uri import android.os.Build import android.os.Environment import android.provider.MediaStore +import androidx.annotation.RequiresApi import androidx.core.content.contentValuesOf import androidx.core.net.toUri import eu.kanade.tachiyomi.R @@ -40,18 +42,21 @@ class ImageSaver( val pictureDir = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) + val folderRelativePath = "${Environment.DIRECTORY_PICTURES}/${context.getString(R.string.app_name)}/" + val imageLocation = (image.location as Location.Pictures).relativePath + val contentValues = contentValuesOf( MediaStore.Images.Media.DISPLAY_NAME to image.name, MediaStore.Images.Media.MIME_TYPE to type.mime, - MediaStore.Images.Media.RELATIVE_PATH to - "${Environment.DIRECTORY_PICTURES}/${context.getString(R.string.app_name)}/" + - (image.location as Location.Pictures).relativePath, + MediaStore.Images.Media.RELATIVE_PATH to folderRelativePath + imageLocation, ) - val picture = context.contentResolver.insert( - pictureDir, - contentValues, - ) ?: throw IOException(context.getString(R.string.error_saving_picture)) + val picture = findUriOrDefault(folderRelativePath, "$imageLocation$filename") { + context.contentResolver.insert( + pictureDir, + contentValues, + ) ?: throw IOException(context.getString(R.string.error_saving_picture)) + } try { data().use { input -> @@ -85,6 +90,37 @@ class ImageSaver( return destFile.getUriCompat(context) } + + @RequiresApi(Build.VERSION_CODES.Q) + private fun findUriOrDefault(relativePath: String, imagePath: String, default: () -> Uri): Uri { + val projection = arrayOf( + MediaStore.MediaColumns._ID, + MediaStore.MediaColumns.DISPLAY_NAME, + MediaStore.Images.Media.MIME_TYPE, + MediaStore.MediaColumns.RELATIVE_PATH, + MediaStore.MediaColumns.DATE_MODIFIED, + ) + + val selection = "${MediaStore.MediaColumns.RELATIVE_PATH}='$relativePath' AND " + + "${MediaStore.MediaColumns.DISPLAY_NAME}='$imagePath'" + + context.contentResolver.query( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + projection, + selection, + null, + null, + ).use { cursor -> + if (cursor != null && cursor.count >= 1) { + cursor.moveToFirst().let { + val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)) + + return ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id) + } + } + } + return default() + } } sealed class Image(