← Back to posts Cover image for Flutter Beyond the Screen: Reading and Editing File Metadata (Audio, Image, etc.)

Flutter Beyond the Screen: Reading and Editing File Metadata (Audio, Image, etc.)

· 5 min read
Weekly Digest

The Flutter news you actually need

No spam, ever. Unsubscribe in one click.

Chris
By Chris

Unlocking Hidden Data: A Guide to File Metadata in Flutter

Your Flutter app displays an image from the gallery or plays a song from local storage. The file is there, the bytes are loaded, but what about the story behind those bytes? The timestamp the photo was taken, the artist of the song, the GPS coordinates embedded in a landscape shot—this is file metadata. While Flutter excels at UI and basic file I/O, handling this rich, type-specific metadata requires venturing beyond the standard dart:io package.

Why Metadata Matters

Imagine building a music player that can only show filenames like “track01.mp3,” a photo gallery that can’t sort images by date, or a fitness app that can’t read location data from your run route images. Metadata is the key to professional, feature-rich applications. It transforms a simple file viewer into an organized media library and a basic image display into a powerful photo editor.

The core challenge is that metadata formats are as varied as the file types themselves: ID3 tags for MP3s, EXIF for JPEGs, XMP for RAW images, and more. Flutter doesn’t provide built-in tools to parse these, so we turn to the power of the pub.dev ecosystem.

Reading Image Metadata with exif

For images, the EXIF (Exchangeable Image File Format) data is often the most valuable. It stores camera settings, date, and crucially, GPS location. The exif package is a pure-Dart solution for this.

First, add the dependency:

dependencies:
  exif: ^3.0.0

Here’s a practical function to read the date taken and GPS coordinates from an image file:

import 'dart:io';
import 'package:exif/exif.dart';

Future<Map<String, dynamic>> readImageMetadata(File imageFile) async {
  final bytes = await imageFile.readAsBytes();
  final data = await readExifFromBytes(bytes);

  final metadata = <String, dynamic>{};

  // Extract the original date/time
  if (data.containsKey('Image DateTime')) {
    metadata['dateTaken'] = data['Image DateTime'];
  }

  // Extract GPS Latitude & Longitude
  try {
    final lat = data['GPS GPSLatitude'];
    final latRef = data['GPS GPSLatitudeRef'];
    final lon = data['GPS GPSLongitude'];
    final lonRef = data['GPS GPSLongitudeRef'];

    if (lat != null && lon != null) {
      metadata['latitude'] = _convertGpsCoordinate(lat, latRef);
      metadata['longitude'] = _convertGpsCoordinate(lon, lonRef);
    }
  } catch (e) {
    print('No GPS data found: $e');
  }

  return metadata;
}

double _convertGpsCoordinate(List<dynamic> rationals, String ref) {
  // Rationals are often in [degrees, minutes, seconds] format
  final degrees = rationals[0];
  final minutes = rationals[1];
  final seconds = rationals[2];

  final decimal = degrees + (minutes / 60.0) + (seconds / 3600.0);
  return (ref == 'S' || ref == 'W') ? -decimal : decimal;
}

Common Gotcha: EXIF data is not always present. Network images, screenshots, or edited files may strip this data. Always wrap your parsing logic in try/catch blocks and provide sensible fallbacks.

Managing Audio Metadata with flutter_media_metadata

For audio files, ID3 tags (for MP3) and similar metadata in other formats contain the information users care about. The flutter_media_metadata plugin is an excellent cross-platform choice that works on Android, iOS, and desktop.

Add it to your pubspec.yaml:

dependencies:
  flutter_media_metadata: ^2.0.0

Here’s how you can read the title, artist, and album art from a music file:

import 'package:flutter_media_metadata/flutter_media_metadata.dart';

Future<void> readAudioMetadata(String filePath) async {
  try {
    final metadata = await MetadataRetriever.fromFile(filePath);

    print('Track Title: ${metadata.trackName ?? 'Unknown'}');
    print('Artist: ${metadata.trackArtistNames?.first ?? 'Unknown'}');
    print('Album: ${metadata.albumName ?? 'Unknown'}');
    print('Duration: ${metadata.trackDuration?.inSeconds} seconds');

    // Album art is returned as a Uint8List, which you can display using Image.memory
    if (metadata.albumArt != null) {
      final albumImage = Image.memory(
        metadata.albumArt!,
        height: 100,
        width: 100,
      );
      // Use this widget in your UI
    }
  } catch (e) {
    print('Failed to read metadata: $e');
  }
}

Performance Note: Reading metadata, especially from large files or extracting embedded album art, is an I/O operation. Perform these tasks asynchronously and consider caching the results to avoid re-reading the same file repeatedly as the user scrolls through a list.

Editing Metadata: Proceed with Caution

While reading metadata is relatively straightforward, editing it in-place is a more complex operation. It involves parsing the file structure, modifying specific byte ranges, and rewriting the file without corruption. Many plugins that offer read/write capabilities rely on platform-specific code (Kotlin, Swift) to leverage native libraries.

If your app requires editing, look for plugins that explicitly support writing. Always:

  1. Create a backup: Operate on a copy of the original file.
  2. Test thoroughly: With different file formats and sizes.
  3. Handle errors gracefully: Inform the user if the write operation fails.

Bringing It All Together

By integrating metadata handling, your app gains depth and utility. You can:

  • Build a photo map that plots images by their GPS coordinates.
  • Create a music player that sorts by artist or album.
  • Develop a file manager that shows detailed properties.

Start by adding read-only metadata to enrich your UI. As your needs grow, explore the more advanced tooling for writing metadata. With the right packages, Flutter can handle the data beyond the bytes, turning simple files into rich, interactive content.

This blog is produced with the assistance of AI by a human editor. Learn more

Related Posts

Cover image for Flutter's Hidden Gem: Building Powerful Linux Desktop Apps with Ease

Flutter's Hidden Gem: Building Powerful Linux Desktop Apps with Ease

Flutter is gaining traction as a robust framework for Linux desktop development, offering a smoother experience compared to traditional toolkits like GTK and Qt. This post will explore why Flutter excels for Linux apps, highlight its advantages, and provide practical insights for developers looking to leverage Flutter for their desktop projects.

Cover image for Simplifying Flutter Desktop Deployment: Signing and Distribution for Windows

Simplifying Flutter Desktop Deployment: Signing and Distribution for Windows

Deploying Flutter desktop apps on Windows can be challenging, especially regarding code signing and preventing Windows from blocking installations. This post will guide developers through the process of signing their Flutter desktop applications, exploring alternatives to the Microsoft Store like creating executable installers, and covering the necessary steps to ensure a smooth user experience.

Cover image for Mastering Flutter Tooling: Streamlining SDK Management and Installation on Windows

Mastering Flutter Tooling: Streamlining SDK Management and Installation on Windows

Developers frequently voice frustrations about Flutter SDK version management and installation processes, particularly on Windows. This post will explore best practices for managing multiple Flutter versions using tools like FVM, discuss integrating Flutter with package managers like Winget for a smoother Windows setup, and offer strategies to ensure a consistent development environment across projects and teams.