From 674eb96bcca26add403c6fcdc817d43d554b5c21 Mon Sep 17 00:00:00 2001 From: Tyler Lopez <77797048+Tyler-Lopez@users.noreply.github.com> Date: Sat, 18 Feb 2023 20:33:51 -0500 Subject: [PATCH] Increment version, make images either png or jpeg dependent on trans (#30) * It was observed that some platforms (like Strava) do not allow for sharing a .png, but do for a .jpg. To get around this, we will only generate .png files when we need to - when the background is transparent. --- app/build.gradle | 4 +- .../data/repository/FileRepositoryImpl.kt | 74 +++++++++++++------ .../domain/repository/FileRepository.kt | 10 ++- .../saveArtScreen/SaveArtViewModel.kt | 16 +++- 4 files changed, 77 insertions(+), 27 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d908f81f..35d59a98 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { applicationId "com.activityartapp" minSdk 26 targetSdk 33 - versionCode 12 - versionName "1.3.2" + versionCode 13 + versionName "1.3.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/com/activityartapp/data/repository/FileRepositoryImpl.kt b/app/src/main/java/com/activityartapp/data/repository/FileRepositoryImpl.kt index 49305789..84601639 100644 --- a/app/src/main/java/com/activityartapp/data/repository/FileRepositoryImpl.kt +++ b/app/src/main/java/com/activityartapp/data/repository/FileRepositoryImpl.kt @@ -21,21 +21,31 @@ class FileRepositoryImpl @Inject constructor( private val context: Context ) : FileRepository { - override suspend fun saveBitmapToGallery(bitmap: Bitmap): Response { + companion object { + private const val EXTENSION_PNG = ".png" + private const val EXTENSION_JPG = ".jpeg" + private const val MIME_TYPE_PNG = "image/png" + private const val MIME_TYPE_JPG = "image/jpeg" + private const val FILENAME_CACHED = "activity_art" + } + + override suspend fun saveBitmapToGallery( + bitmap: Bitmap, + withTransparency: Boolean + ): Response { return try { - val fileName = System.currentTimeMillis().toString() + ".png" + val extension = if (withTransparency) EXTENSION_PNG else EXTENSION_JPG + val fileName = System.currentTimeMillis().toString() + extension val resolver = context.contentResolver - println("Here saving bitmap to gallery") - val uri: Uri? = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { - println("Here saving to gallery when Build is > Q") + val uri: Uri = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { /** * https://stackoverflow.com/questions/8560501/android-save-image-into-gallery * https://stackoverflow.com/questions/57726896/mediastore-images-media-insertimage-deprecated */ resolver.insert( MediaStore.Downloads.EXTERNAL_CONTENT_URI, - initializeContentValues(fileName).apply { + initializeContentValues(fileName, withTransparency).apply { put( MediaStore.MediaColumns.RELATIVE_PATH, DIRECTORY_DOWNLOADS @@ -43,7 +53,6 @@ class FileRepositoryImpl @Inject constructor( } ) } else { - println("Here saving to gallery when Build is < Q") val file = File( Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES), fileName @@ -51,15 +60,19 @@ class FileRepositoryImpl @Inject constructor( /** MediaStore.Images.Media.DATA is deprecated in API 29 **/ resolver.insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - initializeContentValues(fileName).apply { + initializeContentValues(fileName, withTransparency).apply { put(MediaStore.Images.Media.DATA, file.absolutePath) } ) - } + } ?: error("Null URI returned.") - uri?.let { - resolver.openOutputStream(it)?.apply { - bitmap.compressAsPng(this) + runCatching { + resolver.openOutputStream(uri)?.apply { + if (withTransparency) { + bitmap.compressAsPng(this) + } else { + bitmap.compressAsJpeg(this) + } flushAndClose() } } @@ -70,16 +83,27 @@ class FileRepositoryImpl @Inject constructor( } } - override suspend fun saveBitmapToCache(bitmap: Bitmap): Response { + override suspend fun saveBitmapToCache( + bitmap: Bitmap, + withTransparency: Boolean + ): Response { return try { val imageFolder = File(context.cacheDir, "images") imageFolder.mkdirs() - println("Image folder made") - val file = File(imageFolder, "cached_image.png") - FileOutputStream(file).apply { - bitmap.compressAsPng(outputStream = this) - flushAndClose() + val extension = if (withTransparency) EXTENSION_PNG else EXTENSION_JPG + val file = File(imageFolder, FILENAME_CACHED + extension) + + runCatching { + FileOutputStream(file).apply { + if (withTransparency) { + bitmap.compressAsPng(this) + } else { + bitmap.compressAsJpeg(this) + } + flushAndClose() + } } + Response.Success(FileProvider.getUriForFile(context, "com.activityartapp", file)) } catch (e: Exception) { println("Here exception caught saving to cache, $e") @@ -87,10 +111,14 @@ class FileRepositoryImpl @Inject constructor( } } - private fun initializeContentValues(fileName: String): ContentValues = ContentValues().apply { + private fun initializeContentValues( + fileName: String, + withTransparency: Boolean + ): ContentValues = ContentValues().apply { put(MediaStore.MediaColumns.DISPLAY_NAME, fileName) - put(MediaStore.MediaColumns.MIME_TYPE, "image/png") - put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000) + val mimeType = if (withTransparency) MIME_TYPE_PNG else MIME_TYPE_JPG + put(MediaStore.MediaColumns.MIME_TYPE, mimeType) + put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()) put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()) } @@ -98,6 +126,10 @@ class FileRepositoryImpl @Inject constructor( compress(Bitmap.CompressFormat.PNG, 100, outputStream) } + private fun Bitmap.compressAsJpeg(outputStream: OutputStream) { + compress(Bitmap.CompressFormat.JPEG, 100, outputStream) + } + private fun OutputStream.flushAndClose() { flush() close() diff --git a/app/src/main/java/com/activityartapp/domain/repository/FileRepository.kt b/app/src/main/java/com/activityartapp/domain/repository/FileRepository.kt index dd39c979..0008f9ed 100644 --- a/app/src/main/java/com/activityartapp/domain/repository/FileRepository.kt +++ b/app/src/main/java/com/activityartapp/domain/repository/FileRepository.kt @@ -5,6 +5,12 @@ import android.net.Uri import com.activityartapp.util.Response interface FileRepository { - suspend fun saveBitmapToGallery(bitmap: Bitmap): Response - suspend fun saveBitmapToCache(bitmap: Bitmap): Response + suspend fun saveBitmapToGallery( + bitmap: Bitmap, + withTransparency: Boolean + ): Response + suspend fun saveBitmapToCache( + bitmap: Bitmap, + withTransparency: Boolean + ): Response } \ No newline at end of file diff --git a/app/src/main/java/com/activityartapp/presentation/saveArtScreen/SaveArtViewModel.kt b/app/src/main/java/com/activityartapp/presentation/saveArtScreen/SaveArtViewModel.kt index a1b98549..36d1046d 100644 --- a/app/src/main/java/com/activityartapp/presentation/saveArtScreen/SaveArtViewModel.kt +++ b/app/src/main/java/com/activityartapp/presentation/saveArtScreen/SaveArtViewModel.kt @@ -91,7 +91,13 @@ class SaveArtViewModel @Inject constructor( viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.Default) { fileRepository - .saveBitmapToGallery(createArtBitmapOfSize(false, sizePx)) + .saveBitmapToGallery( + bitmap = createArtBitmapOfSize( + isPreview = false, + size = sizePx + ), + withTransparency = backgroundType == BackgroundType.TRANSPARENT + ) .doOnSuccess { pushUpdateToDownloadShareStatus(DOWNLOAD_SUCCESS) } .doOnError { pushUpdateToDownloadShareStatus(DOWNLOAD_FAILURE) } } @@ -119,7 +125,13 @@ class SaveArtViewModel @Inject constructor( pushUpdateToDownloadShareStatus(SHARE_IN_PROGRESS) viewModelScope.launch(Dispatchers.IO) { fileRepository - .saveBitmapToCache(createArtBitmapOfSize(false, sizePx)) + .saveBitmapToCache( + bitmap = createArtBitmapOfSize( + isPreview = false, + size = sizePx + ), + withTransparency = backgroundType == BackgroundType.TRANSPARENT + ) .doOnSuccess { withContext(Dispatchers.Main) { routeTo(ShareFile(data))