fixed opening file media URI with no mime type in Media Store

This commit is contained in:
Thibault Deckers 2020-11-16 12:30:48 +09:00
parent edb8796ba2
commit 93e385d7c3
2 changed files with 42 additions and 35 deletions

View file

@ -47,10 +47,10 @@ class MediaStoreImageProvider : ImageProvider() {
val contentUri = ContentUris.withAppendedId(VIDEO_CONTENT_URI, id) val contentUri = ContentUris.withAppendedId(VIDEO_CONTENT_URI, id)
if (fetchFrom(context, alwaysValid, onSuccess, contentUri, VIDEO_PROJECTION) > 0) return if (fetchFrom(context, alwaysValid, onSuccess, contentUri, VIDEO_PROJECTION) > 0) return
} }
// the uri can be a file media uri (e.g. "content://0@media/external/file/30050") // the uri can be a file media URI (e.g. "content://0@media/external/file/30050")
// without an equivalent image/video if it is shared from a file browser // without an equivalent image/video if it is shared from a file browser
// but the file is not publicly visible // but the file is not publicly visible
if (fetchFrom(context, alwaysValid, onSuccess, uri, BASE_PROJECTION) > 0) return if (fetchFrom(context, alwaysValid, onSuccess, uri, BASE_PROJECTION, fileMimeType = mimeType) > 0) return
callback.onFailure(Exception("failed to fetch entry at uri=$uri")) callback.onFailure(Exception("failed to fetch entry at uri=$uri"))
} }
@ -87,6 +87,7 @@ class MediaStoreImageProvider : ImageProvider() {
handleNewEntry: NewEntryHandler, handleNewEntry: NewEntryHandler,
contentUri: Uri, contentUri: Uri,
projection: Array<String>, projection: Array<String>,
fileMimeType: String? = null,
): Int { ): Int {
var newEntryCount = 0 var newEntryCount = 0
val orderBy = "${MediaStore.MediaColumns.DATE_MODIFIED} DESC" val orderBy = "${MediaStore.MediaColumns.DATE_MODIFIED} DESC"
@ -123,45 +124,51 @@ class MediaStoreImageProvider : ImageProvider() {
// for multiple items, `contentUri` is the root without ID, // for multiple items, `contentUri` is the root without ID,
// but for single items, `contentUri` already contains the ID // but for single items, `contentUri` already contains the ID
val itemUri = if (contentUriContainsId) contentUri else ContentUris.withAppendedId(contentUri, contentId.toLong()) val itemUri = if (contentUriContainsId) contentUri else ContentUris.withAppendedId(contentUri, contentId.toLong())
val mimeType = cursor.getString(mimeTypeColumn) // `mimeType` can be registered as null for file media URIs with unsupported media types (e.g. TIFF on old devices)
// in that case we try to use the mime type provided along the URI
val mimeType: String? = cursor.getString(mimeTypeColumn) ?: fileMimeType
val width = cursor.getInt(widthColumn) val width = cursor.getInt(widthColumn)
val height = cursor.getInt(heightColumn) val height = cursor.getInt(heightColumn)
val durationMillis = if (durationColumn != -1) cursor.getLong(durationColumn) else 0L val durationMillis = if (durationColumn != -1) cursor.getLong(durationColumn) else 0L
var entryMap: FieldMap = hashMapOf( if (mimeType == null) {
"uri" to itemUri.toString(), Log.w(LOG_TAG, "failed to make entry from uri=$itemUri because of null MIME type")
"path" to cursor.getString(pathColumn), } else {
"sourceMimeType" to mimeType, var entryMap: FieldMap = hashMapOf(
"width" to width, "uri" to itemUri.toString(),
"height" to height, "path" to cursor.getString(pathColumn),
"sourceRotationDegrees" to if (orientationColumn != -1) cursor.getInt(orientationColumn) else 0, "sourceMimeType" to mimeType,
"sizeBytes" to cursor.getLong(sizeColumn), "width" to width,
"title" to cursor.getString(titleColumn), "height" to height,
"dateModifiedSecs" to dateModifiedSecs, "sourceRotationDegrees" to if (orientationColumn != -1) cursor.getInt(orientationColumn) else 0,
"sourceDateTakenMillis" to if (dateTakenColumn != -1) cursor.getLong(dateTakenColumn) else null, "sizeBytes" to cursor.getLong(sizeColumn),
"durationMillis" to durationMillis, "title" to cursor.getString(titleColumn),
// only for map export "dateModifiedSecs" to dateModifiedSecs,
"contentId" to contentId, "sourceDateTakenMillis" to if (dateTakenColumn != -1) cursor.getLong(dateTakenColumn) else null,
) "durationMillis" to durationMillis,
// only for map export
"contentId" to contentId,
)
if (MimeTypes.isRaw(mimeType) if (MimeTypes.isRaw(mimeType)
|| (width <= 0 || height <= 0) && needSize(mimeType) || (width <= 0 || height <= 0) && needSize(mimeType)
|| durationMillis == 0L && needDuration || durationMillis == 0L && needDuration
) { ) {
// Some images are incorrectly registered in the Media Store, // Some images are incorrectly registered in the Media Store,
// missing some attributes such as width, height, orientation. // missing some attributes such as width, height, orientation.
// Also, the reported size of raw images is inconsistent across devices // Also, the reported size of raw images is inconsistent across devices
// and Android versions (sometimes the raw size, sometimes the decoded size). // and Android versions (sometimes the raw size, sometimes the decoded size).
val entry = SourceImageEntry(entryMap).fillPreCatalogMetadata(context) val entry = SourceImageEntry(entryMap).fillPreCatalogMetadata(context)
entryMap = entry.toMap() entryMap = entry.toMap()
} }
handleNewEntry(entryMap) handleNewEntry(entryMap)
// TODO TLAD is this necessary? // TODO TLAD is this necessary?
if (newEntryCount % 30 == 0) { if (newEntryCount % 30 == 0) {
delay(10) delay(10)
}
newEntryCount++
} }
newEntryCount++
} }
} }
cursor.close() cursor.close()

View file

@ -44,7 +44,7 @@ object MimeTypes {
else -> isVideo(mimeType) else -> isVideo(mimeType)
} }
fun isRaw(mimeType: String?): Boolean { fun isRaw(mimeType: String): Boolean {
return when (mimeType) { return when (mimeType) {
ARW, CR2, DNG, NEF, NRW, ORF, PEF, RAF, RW2, SRW -> true ARW, CR2, DNG, NEF, NRW, ORF, PEF, RAF, RW2, SRW -> true
else -> false else -> false