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 MetadataService { static const platform = MethodChannel('deckers.thibault/aves/metadata'); // return Map> (map of directories, each directory being a map of metadata label and value description) static Future getAllMetadata(ImageEntry entry) async { if (entry.isSvg) return null; try { final result = await platform.invokeMethod('getAllMetadata', { 'mimeType': entry.mimeType, 'uri': entry.uri, }); return result as Map; } on PlatformException catch (e) { debugPrint('getAllMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}'); } return {}; } static Future getCatalogMetadata(ImageEntry entry, {bool background = false}) async { if (entry.isSvg) return null; Future call() async { try { // return map with: // 'mimeType': MIME type as reported by metadata extractors, not Media Store (string) // 'dateMillis': date taken in milliseconds since Epoch (long) // 'isAnimated': animated gif/webp (bool) // 'isFlipped': flipped according to EXIF orientation (bool) // 'rotationDegrees': rotation degrees according to EXIF orientation or other metadata (int) // 'latitude': latitude (double) // 'longitude': longitude (double) // 'xmpSubjects': ';' separated XMP subjects (string) // 'xmpTitleDescription': XMP title or XMP description (string) final result = await platform.invokeMethod('getCatalogMetadata', { 'mimeType': entry.mimeType, 'uri': entry.uri, 'extension': entry.extension, }) as Map; result['contentId'] = entry.contentId; return CatalogMetadata.fromMap(result); } on PlatformException catch (e) { debugPrint('getCatalogMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}'); } return null; } return background ? servicePolicy.call( call, priority: ServiceCallPriority.getMetadata, ) : call(); } static Future getOverlayMetadata(ImageEntry entry) async { if (entry.isSvg) return null; try { // return map with string descriptions for: 'aperture' 'exposureTime' 'focalLength' 'iso' final result = await platform.invokeMethod('getOverlayMetadata', { 'mimeType': entry.mimeType, 'uri': entry.uri, }) as Map; return OverlayMetadata.fromMap(result); } on PlatformException catch (e) { debugPrint('getOverlayMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}'); } return null; } static Future getContentResolverMetadata(ImageEntry entry) async { try { // return map with all data available from the content resolver final result = await platform.invokeMethod('getContentResolverMetadata', { '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 getExifInterfaceMetadata(ImageEntry entry) async { try { // return map with all data available from the ExifInterface library final result = await platform.invokeMethod('getExifInterfaceMetadata', { 'uri': entry.uri, }) as Map; return result; } on PlatformException catch (e) { debugPrint('getExifInterfaceMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}'); } return {}; } static Future getMediaMetadataRetrieverMetadata(ImageEntry entry) async { try { // return map with all data available from the MediaMetadataRetriever final result = await platform.invokeMethod('getMediaMetadataRetrieverMetadata', { '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> getEmbeddedPictures(String uri) async { try { final result = await platform.invokeMethod('getEmbeddedPictures', { 'uri': uri, }); return (result as List).cast(); } on PlatformException catch (e) { debugPrint('getEmbeddedPictures failed with code=${e.code}, exception=${e.message}, details=${e.details}'); } return []; } static Future> getExifThumbnails(String uri) async { try { final result = await platform.invokeMethod('getExifThumbnails', { 'uri': uri, }); return (result as List).cast(); } on PlatformException catch (e) { debugPrint('getExifThumbnail failed with code=${e.code}, exception=${e.message}, details=${e.details}'); } return []; } static Future> getXmpThumbnails(ImageEntry entry) async { try { final result = await platform.invokeMethod('getXmpThumbnails', { 'mimeType': entry.mimeType, 'uri': entry.uri, }); return (result as List).cast(); } on PlatformException catch (e) { debugPrint('getXmpThumbnail failed with code=${e.code}, exception=${e.message}, details=${e.details}'); } return []; } }