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
This commit is contained in:
Nik Clayton 2023-01-21 14:54:40 +01:00 committed by GitHub
parent db91b4db0e
commit b8f4de9922
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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<UploadEvent> {
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(