From 74dd67642caffc034621ba668a35611cbdc77f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BChlbauer?= <59062169+lm41@users.noreply.github.com> Date: Thu, 7 Mar 2024 00:46:36 +0100 Subject: [PATCH] Fix random rotated images in threema (#2369) * fix random rotated images in threema * add filter for the projection * do not filter only for orientation request but also for every other column * Apply the suggestion * get the orientation of the image on insert --- app/build.gradle.kts | 1 + .../clipboard/provider/ClipboardDatabase.kt | 7 +++++- .../provider/ClipboardMediaProvider.kt | 24 ++++++++++++++++++- gradle/libs.versions.toml | 2 ++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d8602b16..be5fb8bb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -221,6 +221,7 @@ dependencies { implementation(libs.androidx.core.splashscreen) implementation(libs.androidx.emoji2) implementation(libs.androidx.emoji2.views) + implementation(libs.androidx.exifinterface) implementation(libs.androidx.navigation.compose) implementation(libs.androidx.profileinstaller) ksp(libs.androidx.room.compiler) diff --git a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/clipboard/provider/ClipboardDatabase.kt b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/clipboard/provider/ClipboardDatabase.kt index c5f758a5..efe978dc 100644 --- a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/clipboard/provider/ClipboardDatabase.kt +++ b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/clipboard/provider/ClipboardDatabase.kt @@ -22,6 +22,7 @@ import android.content.Context import android.database.Cursor import android.net.Uri import android.provider.BaseColumns +import android.provider.MediaStore.Images.Media import android.provider.OpenableColumns import androidx.core.database.getStringOrNull import androidx.lifecycle.LiveData @@ -307,6 +308,7 @@ data class ClipboardFileInfo( @PrimaryKey @ColumnInfo(name=BaseColumns._ID, index=true) val id: Long, @ColumnInfo(name=OpenableColumns.DISPLAY_NAME) val displayName: String, @ColumnInfo(name=OpenableColumns.SIZE) val size: Long, + @ColumnInfo(name=Media.ORIENTATION) val orientation: Int, val mimeTypes: Array, ) { override fun equals(other: Any?): Boolean { @@ -340,6 +342,9 @@ interface ClipboardFilesDao { @Query("SELECT * FROM $CLIPBOARD_FILES_TABLE WHERE ${BaseColumns._ID} == (:uid)") fun getCursorById(uid: Long) : Cursor + @Query("SELECT (:projection) FROM $CLIPBOARD_FILES_TABLE WHERE ${BaseColumns._ID} == (:uid)") + fun getCurserByIdWithColums(uid: Long, projection: String) : Cursor + @Query("DELETE FROM $CLIPBOARD_FILES_TABLE WHERE ${BaseColumns._ID} == (:id)") fun delete(id: Long) @@ -350,7 +355,7 @@ interface ClipboardFilesDao { fun getAll(): List } -@Database(entities = [ClipboardFileInfo::class], version = 1) +@Database(entities = [ClipboardFileInfo::class], version = 2) @TypeConverters(Converters::class) abstract class ClipboardFilesDatabase : RoomDatabase() { abstract fun clipboardFilesDao() : ClipboardFilesDao diff --git a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/clipboard/provider/ClipboardMediaProvider.kt b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/clipboard/provider/ClipboardMediaProvider.kt index d3e6ac82..299294f9 100644 --- a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/clipboard/provider/ClipboardMediaProvider.kt +++ b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/clipboard/provider/ClipboardMediaProvider.kt @@ -25,7 +25,9 @@ import android.content.UriMatcher import android.database.Cursor import android.net.Uri import android.os.ParcelFileDescriptor +import android.provider.MediaStore import android.provider.OpenableColumns +import androidx.exifinterface.media.ExifInterface import dev.patrickgold.florisboard.BuildConfig import dev.patrickgold.florisboard.lib.devtools.flogError import dev.patrickgold.florisboard.lib.kotlin.tryOrNull @@ -91,6 +93,14 @@ class ClipboardMediaProvider : ContentProvider() { sortOrder: String? ): Cursor? { val id = tryOrNull { ContentUris.parseId(uri) } ?: return null + if (projection != null) { + if (projection.contains(MediaStore.Images.Media.ORIENTATION)) { + clipboardFilesDao?.getCurserByIdWithColums(id, MediaStore.Images.Media.ORIENTATION) + } else { + //Return null if the projection query is invalid + return null + } + } return clipboardFilesDao?.getCursorById(id) } @@ -128,11 +138,23 @@ class ClipboardMediaProvider : ContentProvider() { return try { values as ContentValues val mediaUri = Uri.parse(values.getAsString(Columns.MediaUri)) + // Get the orientation of the image + val exifInterface = ExifInterface(context!!.contentResolver.openInputStream(mediaUri)!!) + var rotation = 0 + val orientation = exifInterface.getAttributeInt( + ExifInterface.TAG_ORIENTATION, + ExifInterface.ORIENTATION_NORMAL + ) + when (orientation) { + ExifInterface.ORIENTATION_ROTATE_90 -> rotation = 90 + ExifInterface.ORIENTATION_ROTATE_180 -> rotation = 180 + ExifInterface.ORIENTATION_ROTATE_270 -> rotation = 270 + } val id = ClipboardFileStorage.cloneUri(context!!, mediaUri) val size = ClipboardFileStorage.getFileForId(context!!, id).length() val mimeTypes = values.getAsString(Columns.MimeTypes).split(",").toTypedArray() val displayName = values.getAsString(OpenableColumns.DISPLAY_NAME) - val fileInfo = ClipboardFileInfo(id, displayName, size, mimeTypes) + val fileInfo = ClipboardFileInfo(id, displayName, size, rotation, mimeTypes) cachedFileInfos[id] = fileInfo ioScope.launch { clipboardFilesDao?.insert(fileInfo) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4527eeeb..691763dd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,6 +11,7 @@ androidx-compose-compiler = "1.5.9" androidx-core = "1.12.0" androidx-core-splashscreen = "1.0.1" androidx-emoji2 = "1.3.0" +androidx-exifinterface = "1.3.6" androidx-navigation = "2.7.7" androidx-profileinstaller = "1.3.1" androidx-room = "2.4.3" @@ -50,6 +51,7 @@ androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "androidx-core-splashscreen" } androidx-emoji2 = { module = "androidx.emoji2:emoji2", version.ref = "androidx-emoji2" } androidx-emoji2-views = { module = "androidx.emoji2:emoji2-views", version.ref = "androidx-emoji2" } +androidx-exifinterface = { module = "androidx.exifinterface:exifinterface", version.ref = "androidx-exifinterface" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" } androidx-profileinstaller = { module = "androidx.profileinstaller:profileinstaller", version.ref = "androidx-profileinstaller" } androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "androidx-room" }