From b8f4de9922d85aeb868c2d05907d5fca4a39bb04 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Sat, 21 Jan 2023 14:54:40 +0100 Subject: [PATCH] Sniff MIME type for audio/video files before upload (#3190) MIME type detection for files based on extensions (the `getType()` method) returns incorrect results from DownloadProvider and FileProvider for (at least) .m4a files. Investigation details are in https://github.com/tuskyapp/Tusky/issues/3189 Be safe, and use `MediaMetadataRetriever` to sniff the content of the files to determine the correct type. Fixes https://github.com/tuskyapp/Tusky/issues/3189 --- .../tusky/components/compose/MediaUploader.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaUploader.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaUploader.kt index 7259097c2..eac6d93fa 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaUploader.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaUploader.kt @@ -17,6 +17,8 @@ package com.keylesspalace.tusky.components.compose import android.content.ContentResolver import android.content.Context +import android.media.MediaMetadataRetriever +import android.media.MediaMetadataRetriever.METADATA_KEY_MIMETYPE import android.net.Uri import android.os.Environment import android.util.Log @@ -248,6 +250,19 @@ class MediaUploader @Inject constructor( private suspend fun upload(media: QueuedMedia): Flow { return callbackFlow { var mimeType = contentResolver.getType(media.uri) + + // Android's MIME type suggestions from file extensions is broken for at least + // .m4a files. See https://github.com/tuskyapp/Tusky/issues/3189 for details. + // Sniff the content of the file to determine the actual type. + if (mimeType != null && ( + mimeType.startsWith("audio/", ignoreCase = true) || + mimeType.startsWith("video/", ignoreCase = true) + ) + ) { + val retriever = MediaMetadataRetriever() + retriever.setDataSource(context, media.uri) + mimeType = retriever.extractMetadata(METADATA_KEY_MIMETYPE) + } val map = MimeTypeMap.getSingleton() val fileExtension = map.getExtensionFromMimeType(mimeType) val filename = "%s_%s_%s.%s".format(