For only with Files now

This commit is contained in:
Benoit Marty 2020-09-04 11:07:06 +02:00
parent b31178683c
commit 544bff9f4f
2 changed files with 26 additions and 48 deletions

View File

@ -21,56 +21,46 @@ import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.graphics.Matrix import android.graphics.Matrix
import android.net.Uri
import androidx.core.content.FileProvider
import androidx.exifinterface.media.ExifInterface import androidx.exifinterface.media.ExifInterface
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.internal.di.SessionDownloadsDirectory
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.util.UUID
import java.util.Date
import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
internal class ImageCompressor @Inject constructor( internal class ImageCompressor @Inject constructor() {
@SessionDownloadsDirectory
private val sessionCacheDirectory: File
) {
private val cacheFolder = File(sessionCacheDirectory, "MF")
suspend fun compress( suspend fun compress(
context: Context, context: Context,
imageUri: Uri, imageFile: File,
desiredWidth: Int, desiredWidth: Int,
desiredHeight: Int, desiredHeight: Int,
desiredQuality: Int = 80): Uri { desiredQuality: Int = 80): File {
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
val compressedBitmap = BitmapFactory.Options().run { val compressedBitmap = BitmapFactory.Options().run {
inJustDecodeBounds = true inJustDecodeBounds = true
decodeBitmap(context, imageUri, this) decodeBitmap(imageFile, this)
inSampleSize = calculateInSampleSize(outWidth, outHeight, desiredWidth, desiredHeight) inSampleSize = calculateInSampleSize(outWidth, outHeight, desiredWidth, desiredHeight)
inJustDecodeBounds = false inJustDecodeBounds = false
decodeBitmap(context, imageUri, this)?.let { decodeBitmap(imageFile, this)?.let {
rotateBitmap(context, imageUri, it) rotateBitmap(imageFile, it)
} }
} ?: return@withContext imageUri } ?: return@withContext imageFile
val destinationUri = createDestinationUri(context) val destinationFile = createDestinationFile(context)
runCatching { runCatching {
context.contentResolver.openOutputStream(destinationUri).use { destinationFile.outputStream().use {
compressedBitmap.compress(Bitmap.CompressFormat.JPEG, desiredQuality, it) compressedBitmap.compress(Bitmap.CompressFormat.JPEG, desiredQuality, it)
} }
} }
return@withContext destinationUri return@withContext destinationFile
} }
} }
private fun rotateBitmap(context: Context, uri: Uri, bitmap: Bitmap): Bitmap { private fun rotateBitmap(file: File, bitmap: Bitmap): Bitmap {
context.contentResolver.openInputStream(uri)?.use { inputStream -> file.inputStream().use { inputStream ->
try { try {
ExifInterface(inputStream).let { exifInfo -> ExifInterface(inputStream).let { exifInfo ->
val orientation = exifInfo.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) val orientation = exifInfo.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
@ -94,7 +84,7 @@ internal class ImageCompressor @Inject constructor(
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e, "Cannot read orientation: %s", uri.toString()) Timber.e(e, "Cannot read orientation")
} }
} }
return bitmap return bitmap
@ -118,9 +108,9 @@ internal class ImageCompressor @Inject constructor(
return inSampleSize return inSampleSize
} }
private fun decodeBitmap(context: Context, uri: Uri, options: BitmapFactory.Options = BitmapFactory.Options()): Bitmap? { private fun decodeBitmap(file: File, options: BitmapFactory.Options = BitmapFactory.Options()): Bitmap? {
return try { return try {
context.contentResolver.openInputStream(uri)?.use { inputStream -> file.inputStream().use { inputStream ->
BitmapFactory.decodeStream(inputStream, null, options) BitmapFactory.decodeStream(inputStream, null, options)
} }
} catch (e: Exception) { } catch (e: Exception) {
@ -129,19 +119,7 @@ internal class ImageCompressor @Inject constructor(
} }
} }
private fun createDestinationUri(context: Context): Uri { private fun createDestinationFile(context: Context): File {
val file = createTempFile() return File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir)
val authority = "${context.packageName}.mx-sdk.fileprovider"
return FileProvider.getUriForFile(context, authority, file)
}
private fun createTempFile(): File {
if (!cacheFolder.exists()) cacheFolder.mkdirs()
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
return File.createTempFile(
"${timeStamp}_", /* prefix */
".jpg", /* suffix */
cacheFolder /* directory */
)
} }
} }

View File

@ -19,8 +19,6 @@ package org.matrix.android.sdk.internal.session.content
import android.content.Context import android.content.Context
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import androidx.core.net.toFile
import androidx.core.net.toUri
import androidx.work.CoroutineWorker import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
@ -129,7 +127,6 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
inputStream.copyTo(it) inputStream.copyTo(it)
} }
// inputStream.use {
var uploadedThumbnailUrl: String? = null var uploadedThumbnailUrl: String? = null
var uploadedThumbnailEncryptedFileInfo: EncryptedFileInfo? = null var uploadedThumbnailEncryptedFileInfo: EncryptedFileInfo? = null
@ -181,9 +178,10 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
val fileToUpload: File val fileToUpload: File
if (attachment.type == ContentAttachmentData.Type.IMAGE && params.compressBeforeSending) { if (attachment.type == ContentAttachmentData.Type.IMAGE && params.compressBeforeSending) {
fileToUpload = imageCompressor.compress(context, workingFile.toUri(), MAX_IMAGE_SIZE, MAX_IMAGE_SIZE) fileToUpload = imageCompressor.compress(context, workingFile, MAX_IMAGE_SIZE, MAX_IMAGE_SIZE)
.also { compressedUri -> .also { compressedFile ->
context.contentResolver.openInputStream(compressedUri)?.use { // Get new Bitmap size
compressedFile.inputStream().use {
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
val bitmap = BitmapFactory.decodeStream(it, null, options) val bitmap = BitmapFactory.decodeStream(it, null, options)
val fileSize = bitmap?.byteCount ?: 0 val fileSize = bitmap?.byteCount ?: 0
@ -194,7 +192,9 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
) )
} }
} }
.toFile()
// we can delete workingFile
tryThis { workingFile.delete() }
} else { } else {
fileToUpload = workingFile fileToUpload = workingFile
} }
@ -232,7 +232,7 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
} }
Timber.v("## FileService: cache storage updated") Timber.v("## FileService: cache storage updated")
} catch (failure: Throwable) { } catch (failure: Throwable) {
Timber.e(failure, "## FileService: Failed to update fileservice cache") Timber.e(failure, "## FileService: Failed to update file cache")
} }
handleSuccess(params, handleSuccess(params,