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) {
|
private void getAllVideoMetadataFallback(MethodCall call, MethodChannel.Result result) {
|
||||||
String path = call.argument("path");
|
String path = call.argument("path");
|
||||||
String uri = call.argument("uri");
|
String uri = call.argument("uri");
|
||||||
try {
|
|
||||||
Map<String, Map<String, String>> metadataMap = new HashMap<>();
|
Map<String, Map<String, String>> metadataMap = new HashMap<>();
|
||||||
Map<String, String> dirMap = new HashMap<>();
|
Map<String, String> dirMap = new HashMap<>();
|
||||||
// unnamed fallback directory
|
// unnamed fallback directory
|
||||||
metadataMap.put("", dirMap);
|
metadataMap.put("", dirMap);
|
||||||
|
|
||||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||||
|
try {
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
retriever.setDataSource(path);
|
retriever.setDataSource(path);
|
||||||
} else {
|
} else {
|
||||||
|
@ -152,11 +153,11 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
||||||
dirMap.put(kv.getValue(), value);
|
dirMap.put(kv.getValue(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
retriever.release();
|
|
||||||
|
|
||||||
result.success(metadataMap);
|
result.success(metadataMap);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result.error("getAllVideoMetadataFallback-exception", "failed to get metadata for uri=" + uri + ", path=" + path, e.getMessage());
|
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"))) {
|
if (isVideo(call.argument("mimeType"))) {
|
||||||
try {
|
|
||||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||||
|
try {
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
retriever.setDataSource(path);
|
retriever.setDataSource(path);
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,7 +219,6 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
||||||
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
|
String dateString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
|
||||||
String rotationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
|
String rotationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
|
||||||
String locationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
|
String locationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
|
||||||
retriever.release();
|
|
||||||
|
|
||||||
if (dateString != null) {
|
if (dateString != null) {
|
||||||
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
|
long dateMillis = MetadataHelper.parseVideoMetadataDate(dateString);
|
||||||
|
@ -251,6 +251,8 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result.error("getCatalogMetadata-exception", "failed to get video metadata for uri=" + uri + ", path=" + path, e.getMessage());
|
result.error("getCatalogMetadata-exception", "failed to get video metadata for uri=" + uri + ", path=" + path, e.getMessage());
|
||||||
|
} finally {
|
||||||
|
retriever.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.success(metadataMap);
|
result.success(metadataMap);
|
||||||
|
|
|
@ -3,6 +3,7 @@ package deckers.thibault.aves.model.provider;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
|
@ -15,11 +16,17 @@ import android.os.ParcelFileDescriptor;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.util.Log;
|
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.File;
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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) {
|
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:
|
case Constants.MIME_JPEG:
|
||||||
rotateJpeg(activity, path, uri, mimeType, clockwise, callback);
|
rotateJpeg(activity, path, uri, clockwise, callback);
|
||||||
break;
|
break;
|
||||||
case Constants.MIME_PNG:
|
case Constants.MIME_PNG:
|
||||||
rotatePng(activity, path, uri, mimeType, clockwise, callback);
|
rotatePng(activity, path, uri, clockwise, callback);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
callback.onFailure();
|
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;
|
String editablePath = path;
|
||||||
boolean onSdCard = Env.isOnSdCard(activity, path);
|
boolean onSdCard = Env.isOnSdCard(activity, path);
|
||||||
if (onSdCard) {
|
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) {
|
if (path == null) {
|
||||||
callback.onFailure();
|
callback.onFailure();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -34,8 +34,8 @@ class UnknownContentImageProvider extends ImageProvider {
|
||||||
|
|
||||||
// check first metadata with MediaMetadataRetriever
|
// check first metadata with MediaMetadataRetriever
|
||||||
|
|
||||||
try {
|
|
||||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||||
|
try {
|
||||||
retriever.setDataSource(activity, uri);
|
retriever.setDataSource(activity, uri);
|
||||||
|
|
||||||
title = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
|
title = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
|
||||||
|
@ -71,9 +71,10 @@ class UnknownContentImageProvider extends ImageProvider {
|
||||||
if (durationMillisString != null) {
|
if (durationMillisString != null) {
|
||||||
durationMillis = Long.parseLong(durationMillisString);
|
durationMillis = Long.parseLong(durationMillisString);
|
||||||
}
|
}
|
||||||
retriever.release();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// ignore
|
// ignore
|
||||||
|
} finally {
|
||||||
|
retriever.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback to metadata-extractor for known types
|
// fallback to metadata-extractor for known types
|
||||||
|
|
Loading…
Reference in a new issue