fixed rotate with incorrect reported mime type
This commit is contained in:
parent
ec51b1878a
commit
b9dd6becaf
3 changed files with 51 additions and 17 deletions
|
@ -125,13 +125,14 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
|||
private void getAllVideoMetadataFallback(MethodCall call, MethodChannel.Result result) {
|
||||
String path = call.argument("path");
|
||||
String uri = call.argument("uri");
|
||||
try {
|
||||
Map<String, Map<String, String>> metadataMap = new HashMap<>();
|
||||
Map<String, String> dirMap = new HashMap<>();
|
||||
// unnamed fallback directory
|
||||
metadataMap.put("", dirMap);
|
||||
|
||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||
Map<String, Map<String, String>> metadataMap = new HashMap<>();
|
||||
Map<String, String> dirMap = new HashMap<>();
|
||||
// unnamed fallback directory
|
||||
metadataMap.put("", dirMap);
|
||||
|
||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||
try {
|
||||
if (path != null) {
|
||||
retriever.setDataSource(path);
|
||||
} else {
|
||||
|
@ -152,11 +153,11 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
|||
dirMap.put(kv.getValue(), value);
|
||||
}
|
||||
}
|
||||
retriever.release();
|
||||
|
||||
result.success(metadataMap);
|
||||
} catch (Exception e) {
|
||||
result.error("getAllVideoMetadataFallback-exception", "failed to get metadata for uri=" + uri + ", path=" + path, e.getMessage());
|
||||
} finally {
|
||||
retriever.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,8 +209,8 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
|||
}
|
||||
|
||||
if (isVideo(call.argument("mimeType"))) {
|
||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||
try {
|
||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||
if (path != null) {
|
||||
retriever.setDataSource(path);
|
||||
} else {
|
||||
|
@ -218,7 +219,6 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
|||
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
|
||||
String rotationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
|
||||
String locationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
|
||||
retriever.release();
|
||||
|
||||
if (dateString != null) {
|
||||
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
|
||||
|
@ -251,6 +251,8 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
|||
}
|
||||
} catch (Exception e) {
|
||||
result.error("getCatalogMetadata-exception", "failed to get video metadata for uri=" + uri + ", path=" + path, e.getMessage());
|
||||
} finally {
|
||||
retriever.release();
|
||||
}
|
||||
}
|
||||
result.success(metadataMap);
|
||||
|
|
|
@ -3,6 +3,7 @@ package deckers.thibault.aves.model.provider;
|
|||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
@ -15,11 +16,17 @@ import android.os.ParcelFileDescriptor;
|
|||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
|
||||
import com.drew.imaging.ImageMetadataReader;
|
||||
import com.drew.imaging.ImageProcessingException;
|
||||
import com.drew.metadata.Metadata;
|
||||
import com.drew.metadata.file.FileTypeDirectory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -109,20 +116,43 @@ public abstract class ImageProvider {
|
|||
});
|
||||
}
|
||||
|
||||
// file extension is unreliable
|
||||
// `context.getContentResolver().getType()` sometimes return incorrect value
|
||||
// `MediaMetadataRetriever.setDataSource()` sometimes fail with `status = 0x80000000`
|
||||
// so we check with `metadata-extractor`
|
||||
private String getMimeType(final Context context, final Uri uri) {
|
||||
try (InputStream is = context.getContentResolver().openInputStream(uri)) {
|
||||
Metadata metadata = ImageMetadataReader.readMetadata(is);
|
||||
FileTypeDirectory fileTypeDir = metadata.getFirstDirectoryOfType(FileTypeDirectory.class);
|
||||
if (fileTypeDir != null) {
|
||||
if (fileTypeDir.containsTag(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)) {
|
||||
return fileTypeDir.getString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE);
|
||||
}
|
||||
}
|
||||
} catch (IOException | ImageProcessingException e) {
|
||||
Log.w(LOG_TAG, "failed to get mime type from metadata for uri=" + uri, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void rotate(final Activity activity, final String path, final Uri uri, final String mimeType, final boolean clockwise, final ImageOpCallback callback) {
|
||||
switch (mimeType) {
|
||||
// the reported `mimeType` (e.g. from Media Store) is sometimes incorrect
|
||||
// so we retrieve it again from the file metadata
|
||||
String metadataMimeType = getMimeType(activity, uri);
|
||||
switch (metadataMimeType != null ? metadataMimeType : mimeType) {
|
||||
case Constants.MIME_JPEG:
|
||||
rotateJpeg(activity, path, uri, mimeType, clockwise, callback);
|
||||
rotateJpeg(activity, path, uri, clockwise, callback);
|
||||
break;
|
||||
case Constants.MIME_PNG:
|
||||
rotatePng(activity, path, uri, mimeType, clockwise, callback);
|
||||
rotatePng(activity, path, uri, clockwise, callback);
|
||||
break;
|
||||
default:
|
||||
callback.onFailure();
|
||||
}
|
||||
}
|
||||
|
||||
private void rotateJpeg(final Activity activity, final String path, final Uri uri, final String mimeType, boolean clockwise, final ImageOpCallback callback) {
|
||||
private void rotateJpeg(final Activity activity, final String path, final Uri uri, boolean clockwise, final ImageOpCallback callback) {
|
||||
final String mimeType = Constants.MIME_JPEG;
|
||||
String editablePath = path;
|
||||
boolean onSdCard = Env.isOnSdCard(activity, path);
|
||||
if (onSdCard) {
|
||||
|
@ -197,7 +227,8 @@ public abstract class ImageProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private void rotatePng(final Activity activity, final String path, final Uri uri, final String mimeType, boolean clockwise, final ImageOpCallback callback) {
|
||||
private void rotatePng(final Activity activity, final String path, final Uri uri, boolean clockwise, final ImageOpCallback callback) {
|
||||
final String mimeType = Constants.MIME_PNG;
|
||||
if (path == null) {
|
||||
callback.onFailure();
|
||||
return;
|
||||
|
|
|
@ -34,8 +34,8 @@ class UnknownContentImageProvider extends ImageProvider {
|
|||
|
||||
// check first metadata with MediaMetadataRetriever
|
||||
|
||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||
try {
|
||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||
retriever.setDataSource(activity, uri);
|
||||
|
||||
title = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
|
||||
|
@ -71,9 +71,10 @@ class UnknownContentImageProvider extends ImageProvider {
|
|||
if (durationMillisString != null) {
|
||||
durationMillis = Long.parseLong(durationMillisString);
|
||||
}
|
||||
retriever.release();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
} finally {
|
||||
retriever.release();
|
||||
}
|
||||
|
||||
// fallback to metadata-extractor for known types
|
||||
|
|
Loading…
Reference in a new issue