moved debug related functions

This commit is contained in:
Thibault Deckers 2020-12-02 11:09:51 +09:00
parent f205075ac4
commit 4f7287de02
9 changed files with 322 additions and 277 deletions

View file

@ -41,6 +41,7 @@ class MainActivity : FlutterActivity() {
MethodChannel(messenger, ImageFileHandler.CHANNEL).setMethodCallHandler(ImageFileHandler(this))
MethodChannel(messenger, MetadataHandler.CHANNEL).setMethodCallHandler(MetadataHandler(this))
MethodChannel(messenger, StorageHandler.CHANNEL).setMethodCallHandler(StorageHandler(this))
MethodChannel(messenger, DebugHandler.CHANNEL).setMethodCallHandler(DebugHandler(this))
StreamsChannel(messenger, ImageByteStreamHandler.CHANNEL).setStreamHandlerFactory { args -> ImageByteStreamHandler(this, args) }
StreamsChannel(messenger, ImageOpStreamHandler.CHANNEL).setStreamHandlerFactory { args -> ImageOpStreamHandler(this, args) }

View file

@ -29,7 +29,6 @@ class AppAdapterHandler(private val context: Context) : MethodCallHandler {
when (call.method) {
"getAppIcon" -> GlobalScope.launch { getAppIcon(call, Coresult(result)) }
"getAppNames" -> GlobalScope.launch { getAppNames(Coresult(result)) }
"getEnv" -> result.success(System.getenv())
"edit" -> {
val title = call.argument<String>("title")
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }

View file

@ -0,0 +1,222 @@
package deckers.thibault.aves.channel.calls
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.util.Log
import androidx.exifinterface.media.ExifInterface
import com.drew.imaging.ImageMetadataReader
import com.drew.metadata.file.FileTypeDirectory
import deckers.thibault.aves.metadata.ExifInterfaceHelper
import deckers.thibault.aves.metadata.MediaMetadataRetrieverHelper
import deckers.thibault.aves.utils.LogUtils
import deckers.thibault.aves.utils.MimeTypes.isImage
import deckers.thibault.aves.utils.MimeTypes.isSupportedByExifInterface
import deckers.thibault.aves.utils.MimeTypes.isSupportedByMetadataExtractor
import deckers.thibault.aves.utils.MimeTypes.isVideo
import deckers.thibault.aves.utils.StorageUtils
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.IOException
import java.util.*
class DebugHandler(private val context: Context) : MethodCallHandler {
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"getEnv" -> result.success(System.getenv())
"getBitmapFactoryInfo" -> GlobalScope.launch { getBitmapFactoryInfo(call, Coresult(result)) }
"getContentResolverMetadata" -> GlobalScope.launch { getContentResolverMetadata(call, Coresult(result)) }
"getExifInterfaceMetadata" -> GlobalScope.launch { getExifInterfaceMetadata(call, Coresult(result)) }
"getMediaMetadataRetrieverMetadata" -> GlobalScope.launch { getMediaMetadataRetrieverMetadata(call, Coresult(result)) }
"getMetadataExtractorSummary" -> GlobalScope.launch { getMetadataExtractorSummary(call, Coresult(result)) }
else -> result.notImplemented()
}
}
private fun getBitmapFactoryInfo(call: MethodCall, result: MethodChannel.Result) {
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
if (uri == null) {
result.error("getBitmapDecoderInfo-args", "failed because of missing arguments", null)
return
}
val metadataMap = HashMap<String, String>()
try {
StorageUtils.openInputStream(context, uri)?.use { input ->
val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true
}
BitmapFactory.decodeStream(input, null, options)
options.outMimeType?.let { metadataMap["MimeType"] = it }
options.outWidth.takeIf { it >= 0 }?.let { metadataMap["Width"] = it.toString() }
options.outHeight.takeIf { it >= 0 }?.let { metadataMap["Height"] = it.toString() }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
options.outColorSpace?.let { metadataMap["ColorSpace"] = it.toString() }
options.outConfig?.let { metadataMap["Config"] = it.toString() }
}
}
} catch (e: IOException) {
// ignore
}
result.success(metadataMap)
}
private fun getContentResolverMetadata(call: MethodCall, result: MethodChannel.Result) {
val mimeType = call.argument<String>("mimeType")
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
if (mimeType == null || uri == null) {
result.error("getContentResolverMetadata-args", "failed because of missing arguments", null)
return
}
var contentUri: Uri = uri
if (uri.scheme == ContentResolver.SCHEME_CONTENT && MediaStore.AUTHORITY.equals(uri.host, ignoreCase = true)) {
try {
val id = ContentUris.parseId(uri)
contentUri = when {
isImage(mimeType) -> ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)
isVideo(mimeType) -> ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id)
else -> uri
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
contentUri = MediaStore.setRequireOriginal(contentUri)
}
} catch (e: NumberFormatException) {
// ignore
}
}
val cursor = context.contentResolver.query(contentUri, null, null, null, null)
if (cursor != null && cursor.moveToFirst()) {
val metadataMap = HashMap<String, Any?>()
val columnCount = cursor.columnCount
val columnNames = cursor.columnNames
for (i in 0 until columnCount) {
val key = columnNames[i]
try {
metadataMap[key] = when (cursor.getType(i)) {
Cursor.FIELD_TYPE_NULL -> null
Cursor.FIELD_TYPE_INTEGER -> cursor.getLong(i)
Cursor.FIELD_TYPE_FLOAT -> cursor.getFloat(i)
Cursor.FIELD_TYPE_STRING -> cursor.getString(i)
Cursor.FIELD_TYPE_BLOB -> cursor.getBlob(i)
else -> null
}
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to get value for key=$key", e)
}
}
cursor.close()
result.success(metadataMap)
} else {
result.error("getContentResolverMetadata-null", "failed to get cursor for contentUri=$contentUri", null)
}
}
private fun getExifInterfaceMetadata(call: MethodCall, result: MethodChannel.Result) {
val mimeType = call.argument<String>("mimeType")
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
val sizeBytes = call.argument<Number>("sizeBytes")?.toLong()
if (mimeType == null || uri == null) {
result.error("getExifInterfaceMetadata-args", "failed because of missing arguments", null)
return
}
val metadataMap = HashMap<String, String?>()
if (isSupportedByExifInterface(mimeType, sizeBytes, strict = false)) {
try {
StorageUtils.openInputStream(context, uri)?.use { input ->
val exif = ExifInterface(input)
for (tag in ExifInterfaceHelper.allTags.keys.filter { exif.hasAttribute(it) }) {
metadataMap[tag] = exif.getAttribute(tag)
}
}
} catch (e: Exception) {
// ExifInterface initialization can fail with a RuntimeException
// caused by an internal MediaMetadataRetriever failure
result.error("getExifInterfaceMetadata-failure", "failed to get exif for uri=$uri", e.message)
return
}
}
result.success(metadataMap)
}
private fun getMediaMetadataRetrieverMetadata(call: MethodCall, result: MethodChannel.Result) {
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
if (uri == null) {
result.error("getMediaMetadataRetrieverMetadata-args", "failed because of missing arguments", null)
return
}
val metadataMap = HashMap<String, String>()
val retriever = StorageUtils.openMetadataRetriever(context, uri)
if (retriever != null) {
try {
for ((code, name) in MediaMetadataRetrieverHelper.allKeys) {
retriever.extractMetadata(code)?.let { metadataMap[name] = it }
}
} catch (e: Exception) {
// ignore
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release()
}
}
result.success(metadataMap)
}
private fun getMetadataExtractorSummary(call: MethodCall, result: MethodChannel.Result) {
val mimeType = call.argument<String>("mimeType")
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
val sizeBytes = call.argument<Number>("sizeBytes")?.toLong()
if (mimeType == null || uri == null) {
result.error("getMetadataExtractorSummary-args", "failed because of missing arguments", null)
return
}
val metadataMap = HashMap<String, String>()
if (isSupportedByMetadataExtractor(mimeType, sizeBytes)) {
try {
StorageUtils.openInputStream(context, uri)?.use { input ->
val metadata = ImageMetadataReader.readMetadata(input, sizeBytes ?: -1)
metadataMap["mimeType"] = metadata.getDirectoriesOfType(FileTypeDirectory::class.java).joinToString { dir ->
if (dir.containsTag(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)) {
dir.getString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)
} else ""
}
metadataMap["typeName"] = metadata.getDirectoriesOfType(FileTypeDirectory::class.java).joinToString { dir ->
if (dir.containsTag(FileTypeDirectory.TAG_DETECTED_FILE_TYPE_NAME)) {
dir.getString(FileTypeDirectory.TAG_DETECTED_FILE_TYPE_NAME)
} else ""
}
for (dir in metadata.directories) {
val dirName = dir.name ?: ""
var index = 0
while (metadataMap.containsKey("$dirName ($index)")) index++
var value = "${dir.tagCount} tags"
dir.parent?.let { value += ", parent: ${it.name}" }
metadataMap["$dirName ($index)"] = value
}
}
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to get metadata by metadata-extractor for uri=$uri", e)
} catch (e: NoClassDefFoundError) {
Log.w(LOG_TAG, "failed to get metadata by metadata-extractor for uri=$uri", e)
}
}
result.success(metadataMap)
}
companion object {
private val LOG_TAG = LogUtils.createTag(DebugHandler::class.java)
const val CHANNEL = "deckers.thibault/aves/debug"
}
}

View file

@ -1,14 +1,8 @@
package deckers.thibault.aves.channel.calls
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.graphics.BitmapFactory
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.util.Log
import androidx.exifinterface.media.ExifInterface
import com.adobe.internal.xmp.XMPException
@ -25,7 +19,6 @@ import com.drew.metadata.file.FileTypeDirectory
import com.drew.metadata.gif.GifAnimationDirectory
import com.drew.metadata.webp.WebpDirectory
import com.drew.metadata.xmp.XmpDirectory
import deckers.thibault.aves.metadata.ExifInterfaceHelper
import deckers.thibault.aves.metadata.ExifInterfaceHelper.describeAll
import deckers.thibault.aves.metadata.ExifInterfaceHelper.getSafeDateMillis
import deckers.thibault.aves.metadata.ExifInterfaceHelper.getSafeDouble
@ -51,7 +44,6 @@ import deckers.thibault.aves.utils.BitmapUtils
import deckers.thibault.aves.utils.BitmapUtils.getBytes
import deckers.thibault.aves.utils.LogUtils
import deckers.thibault.aves.utils.MimeTypes
import deckers.thibault.aves.utils.MimeTypes.isImage
import deckers.thibault.aves.utils.MimeTypes.isMultimedia
import deckers.thibault.aves.utils.MimeTypes.isSupportedByExifInterface
import deckers.thibault.aves.utils.MimeTypes.isSupportedByMetadataExtractor
@ -63,7 +55,6 @@ import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.IOException
import java.util.*
import kotlin.math.roundToLong
@ -73,11 +64,6 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
"getAllMetadata" -> GlobalScope.launch { getAllMetadata(call, Coresult(result)) }
"getCatalogMetadata" -> GlobalScope.launch { getCatalogMetadata(call, Coresult(result)) }
"getOverlayMetadata" -> GlobalScope.launch { getOverlayMetadata(call, Coresult(result)) }
"getContentResolverMetadata" -> GlobalScope.launch { getContentResolverMetadata(call, Coresult(result)) }
"getExifInterfaceMetadata" -> GlobalScope.launch { getExifInterfaceMetadata(call, Coresult(result)) }
"getMediaMetadataRetrieverMetadata" -> GlobalScope.launch { getMediaMetadataRetrieverMetadata(call, Coresult(result)) }
"getBitmapFactoryInfo" -> GlobalScope.launch { getBitmapFactoryInfo(call, Coresult(result)) }
"getMetadataExtractorSummary" -> GlobalScope.launch { getMetadataExtractorSummary(call, Coresult(result)) }
"getEmbeddedPictures" -> GlobalScope.launch { getEmbeddedPictures(call, Coresult(result)) }
"getExifThumbnails" -> GlobalScope.launch { getExifThumbnails(call, Coresult(result)) }
"getXmpThumbnails" -> GlobalScope.launch { getXmpThumbnails(call, Coresult(result)) }
@ -446,180 +432,6 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
result.success(metadataMap)
}
private fun getContentResolverMetadata(call: MethodCall, result: MethodChannel.Result) {
val mimeType = call.argument<String>("mimeType")
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
if (mimeType == null || uri == null) {
result.error("getContentResolverMetadata-args", "failed because of missing arguments", null)
return
}
var contentUri: Uri = uri
if (uri.scheme == ContentResolver.SCHEME_CONTENT && MediaStore.AUTHORITY.equals(uri.host, ignoreCase = true)) {
try {
val id = ContentUris.parseId(uri)
contentUri = when {
isImage(mimeType) -> ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)
isVideo(mimeType) -> ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id)
else -> uri
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
contentUri = MediaStore.setRequireOriginal(contentUri)
}
} catch (e: NumberFormatException) {
// ignore
}
}
val cursor = context.contentResolver.query(contentUri, null, null, null, null)
if (cursor != null && cursor.moveToFirst()) {
val metadataMap = HashMap<String, Any?>()
val columnCount = cursor.columnCount
val columnNames = cursor.columnNames
for (i in 0 until columnCount) {
val key = columnNames[i]
try {
metadataMap[key] = when (cursor.getType(i)) {
Cursor.FIELD_TYPE_NULL -> null
Cursor.FIELD_TYPE_INTEGER -> cursor.getLong(i)
Cursor.FIELD_TYPE_FLOAT -> cursor.getFloat(i)
Cursor.FIELD_TYPE_STRING -> cursor.getString(i)
Cursor.FIELD_TYPE_BLOB -> cursor.getBlob(i)
else -> null
}
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to get value for key=$key", e)
}
}
cursor.close()
result.success(metadataMap)
} else {
result.error("getContentResolverMetadata-null", "failed to get cursor for contentUri=$contentUri", null)
}
}
private fun getExifInterfaceMetadata(call: MethodCall, result: MethodChannel.Result) {
val mimeType = call.argument<String>("mimeType")
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
val sizeBytes = call.argument<Number>("sizeBytes")?.toLong()
if (mimeType == null || uri == null) {
result.error("getExifInterfaceMetadata-args", "failed because of missing arguments", null)
return
}
val metadataMap = HashMap<String, String?>()
if (isSupportedByExifInterface(mimeType, sizeBytes, strict = false)) {
try {
StorageUtils.openInputStream(context, uri)?.use { input ->
val exif = ExifInterface(input)
for (tag in ExifInterfaceHelper.allTags.keys.filter { exif.hasAttribute(it) }) {
metadataMap[tag] = exif.getAttribute(tag)
}
}
} catch (e: Exception) {
// ExifInterface initialization can fail with a RuntimeException
// caused by an internal MediaMetadataRetriever failure
result.error("getExifInterfaceMetadata-failure", "failed to get exif for uri=$uri", e.message)
return
}
}
result.success(metadataMap)
}
private fun getMediaMetadataRetrieverMetadata(call: MethodCall, result: MethodChannel.Result) {
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
if (uri == null) {
result.error("getMediaMetadataRetrieverMetadata-args", "failed because of missing arguments", null)
return
}
val metadataMap = HashMap<String, String>()
val retriever = StorageUtils.openMetadataRetriever(context, uri)
if (retriever != null) {
try {
for ((code, name) in MediaMetadataRetrieverHelper.allKeys) {
retriever.extractMetadata(code)?.let { metadataMap[name] = it }
}
} catch (e: Exception) {
// ignore
} finally {
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
retriever.release()
}
}
result.success(metadataMap)
}
private fun getBitmapFactoryInfo(call: MethodCall, result: MethodChannel.Result) {
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
if (uri == null) {
result.error("getBitmapDecoderInfo-args", "failed because of missing arguments", null)
return
}
val metadataMap = HashMap<String, String>()
try {
StorageUtils.openInputStream(context, uri)?.use { input ->
val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true
}
BitmapFactory.decodeStream(input, null, options)
options.outMimeType?.let { metadataMap["MimeType"] = it }
options.outWidth.takeIf { it >= 0 }?.let { metadataMap["Width"] = it.toString() }
options.outHeight.takeIf { it >= 0 }?.let { metadataMap["Height"] = it.toString() }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
options.outColorSpace?.let { metadataMap["ColorSpace"] = it.toString() }
options.outConfig?.let { metadataMap["Config"] = it.toString() }
}
}
} catch (e: IOException) {
// ignore
}
result.success(metadataMap)
}
private fun getMetadataExtractorSummary(call: MethodCall, result: MethodChannel.Result) {
val mimeType = call.argument<String>("mimeType")
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
val sizeBytes = call.argument<Number>("sizeBytes")?.toLong()
if (mimeType == null || uri == null) {
result.error("getMetadataExtractorSummary-args", "failed because of missing arguments", null)
return
}
val metadataMap = HashMap<String, String>()
if (isSupportedByMetadataExtractor(mimeType, sizeBytes)) {
try {
StorageUtils.openInputStream(context, uri)?.use { input ->
val metadata = ImageMetadataReader.readMetadata(input, sizeBytes ?: -1)
metadataMap["mimeType"] = metadata.getDirectoriesOfType(FileTypeDirectory::class.java).joinToString { dir ->
if (dir.containsTag(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)) {
dir.getString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)
} else ""
}
metadataMap["typeName"] = metadata.getDirectoriesOfType(FileTypeDirectory::class.java).joinToString { dir ->
if (dir.containsTag(FileTypeDirectory.TAG_DETECTED_FILE_TYPE_NAME)) {
dir.getString(FileTypeDirectory.TAG_DETECTED_FILE_TYPE_NAME)
} else ""
}
for (dir in metadata.directories) {
val dirName = dir.name ?: ""
var index = 0
while (metadataMap.containsKey("$dirName ($index)")) index++
var value = "${dir.tagCount} tags"
dir.parent?.let { value += ", parent: ${it.name}" }
metadataMap["$dirName ($index)"] = value
}
}
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to get metadata by metadata-extractor for uri=$uri", e)
} catch (e: NoClassDefFoundError) {
Log.w(LOG_TAG, "failed to get metadata by metadata-extractor for uri=$uri", e)
}
}
result.success(metadataMap)
}
private fun getEmbeddedPictures(call: MethodCall, result: MethodChannel.Result) {
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
if (uri == null) {

View file

@ -31,16 +31,6 @@ class AndroidAppService {
return null;
}
static Future<Map> getEnv() async {
try {
final result = await platform.invokeMethod('getEnv');
return result as Map;
} on PlatformException catch (e) {
debugPrint('getEnv failed with code=${e.code}, exception=${e.message}, details=${e.details}}');
}
return {};
}
static Future<bool> edit(String uri, String mimeType) async {
try {
return await platform.invokeMethod('edit', <String, dynamic>{

View file

@ -0,0 +1,91 @@
import 'dart:typed_data';
import 'package:aves/model/image_entry.dart';
import 'package:aves/model/image_metadata.dart';
import 'package:aves/services/service_policy.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
class AndroidDebugService {
static const platform = MethodChannel('deckers.thibault/aves/debug');
static Future<Map> getEnv() async {
try {
final result = await platform.invokeMethod('getEnv');
return result as Map;
} on PlatformException catch (e) {
debugPrint('getEnv failed with code=${e.code}, exception=${e.message}, details=${e.details}}');
}
return {};
}
static Future<Map> getBitmapFactoryInfo(ImageEntry entry) async {
try {
// return map with all data available when decoding image bounds with `BitmapFactory`
final result = await platform.invokeMethod('getBitmapFactoryInfo', <String, dynamic>{
'uri': entry.uri,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getBitmapFactoryInfo failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
static Future<Map> getContentResolverMetadata(ImageEntry entry) async {
try {
// return map with all data available from the content resolver
final result = await platform.invokeMethod('getContentResolverMetadata', <String, dynamic>{
'mimeType': entry.mimeType,
'uri': entry.uri,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getContentResolverMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
static Future<Map> getExifInterfaceMetadata(ImageEntry entry) async {
try {
// return map with all data available from the `ExifInterface` library
final result = await platform.invokeMethod('getExifInterfaceMetadata', <String, dynamic>{
'mimeType': entry.mimeType,
'uri': entry.uri,
'sizeBytes': entry.sizeBytes,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getExifInterfaceMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
static Future<Map> getMediaMetadataRetrieverMetadata(ImageEntry entry) async {
try {
// return map with all data available from `MediaMetadataRetriever`
final result = await platform.invokeMethod('getMediaMetadataRetrieverMetadata', <String, dynamic>{
'uri': entry.uri,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getMediaMetadataRetrieverMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
static Future<Map> getMetadataExtractorSummary(ImageEntry entry) async {
try {
// return map with the mime type and tag count for each directory found by `metadata-extractor`
final result = await platform.invokeMethod('getMetadataExtractorSummary', <String, dynamic>{
'mimeType': entry.mimeType,
'uri': entry.uri,
'sizeBytes': entry.sizeBytes,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getMetadataExtractorSummary failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
}

View file

@ -80,76 +80,6 @@ class MetadataService {
return null;
}
static Future<Map> getBitmapFactoryInfo(ImageEntry entry) async {
try {
// return map with all data available when decoding image bounds with `BitmapFactory`
final result = await platform.invokeMethod('getBitmapFactoryInfo', <String, dynamic>{
'uri': entry.uri,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getBitmapFactoryInfo failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
static Future<Map> getContentResolverMetadata(ImageEntry entry) async {
try {
// return map with all data available from the content resolver
final result = await platform.invokeMethod('getContentResolverMetadata', <String, dynamic>{
'mimeType': entry.mimeType,
'uri': entry.uri,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getContentResolverMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
static Future<Map> getExifInterfaceMetadata(ImageEntry entry) async {
try {
// return map with all data available from the `ExifInterface` library
final result = await platform.invokeMethod('getExifInterfaceMetadata', <String, dynamic>{
'mimeType': entry.mimeType,
'uri': entry.uri,
'sizeBytes': entry.sizeBytes,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getExifInterfaceMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
static Future<Map> getMediaMetadataRetrieverMetadata(ImageEntry entry) async {
try {
// return map with all data available from `MediaMetadataRetriever`
final result = await platform.invokeMethod('getMediaMetadataRetrieverMetadata', <String, dynamic>{
'uri': entry.uri,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getMediaMetadataRetrieverMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
static Future<Map> getMetadataExtractorSummary(ImageEntry entry) async {
try {
// return map with the mime type and tag count for each directory found by `metadata-extractor`
final result = await platform.invokeMethod('getMetadataExtractorSummary', <String, dynamic>{
'mimeType': entry.mimeType,
'uri': entry.uri,
'sizeBytes': entry.sizeBytes,
}) as Map;
return result;
} on PlatformException catch (e) {
debugPrint('getMetadataExtractorSummary failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}
return {};
}
static Future<List<Uint8List>> getEmbeddedPictures(String uri) async {
try {
final result = await platform.invokeMethod('getEmbeddedPictures', <String, dynamic>{

View file

@ -1,6 +1,6 @@
import 'dart:collection';
import 'package:aves/services/android_app_service.dart';
import 'package:aves/services/android_debug_service.dart';
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
import 'package:aves/widgets/fullscreen/info/common.dart';
import 'package:flutter/material.dart';
@ -16,7 +16,7 @@ class _DebugAndroidEnvironmentSectionState extends State<DebugAndroidEnvironment
@override
void initState() {
super.initState();
_loader = AndroidAppService.getEnv();
_loader = AndroidDebugService.getEnv();
}
@override

View file

@ -2,7 +2,7 @@ import 'dart:collection';
import 'dart:typed_data';
import 'package:aves/model/image_entry.dart';
import 'package:aves/services/metadata_service.dart';
import 'package:aves/services/android_debug_service.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
import 'package:aves/widgets/fullscreen/info/common.dart';
@ -33,11 +33,11 @@ class _MetadataTabState extends State<MetadataTab> {
}
void _loadMetadata() {
_bitmapFactoryLoader = MetadataService.getBitmapFactoryInfo(entry);
_contentResolverMetadataLoader = MetadataService.getContentResolverMetadata(entry);
_exifInterfaceMetadataLoader = MetadataService.getExifInterfaceMetadata(entry);
_mediaMetadataLoader = MetadataService.getMediaMetadataRetrieverMetadata(entry);
_metadataExtractorLoader = MetadataService.getMetadataExtractorSummary(entry);
_bitmapFactoryLoader = AndroidDebugService.getBitmapFactoryInfo(entry);
_contentResolverMetadataLoader = AndroidDebugService.getContentResolverMetadata(entry);
_exifInterfaceMetadataLoader = AndroidDebugService.getExifInterfaceMetadata(entry);
_mediaMetadataLoader = AndroidDebugService.getMediaMetadataRetrieverMetadata(entry);
_metadataExtractorLoader = AndroidDebugService.getMetadataExtractorSummary(entry);
setState(() {});
}