Skip to content

[image_picker] Image Exif data Lat/Lng missing when image is picked using camera #170205

Open
@maheshj01

Description

@maheshj01

Steps to reproduce

  1. Create a new flutter project with following packages
  image: ^4.1.7
  exif: ^3.3.0
  image_picker: ^1.1.2
  permission_handler: ^11.3.1
  1. Add the following permissions (probably you only need ACCESS_MEDIA_LOCATION)
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
  1. Run the below code sample
  2. Pick image using camera notice exif data does not contain GPS data (latitude or longitude) is not shown, However if you pick a image from your gallery (photo that was taken on your device) has this data

I have only tested this on Android and not sure about IOS

Expected results

Location data should be shown when image is selected via camera

ImageSource.gallery
I/flutter (30859): Path : /data/user/0/com.example.flutter_meta_data/cache/0503592e-1538-4ea6-b57f-cb9e14dfd3be/1000051119.jpg
I/flutter (30859): Image Make: Google
I/flutter (30859): Image Model: Pixel 7
I/flutter (30859): Image Orientation: Horizontal (normal)
I/flutter (30859): Image XResolution: 72
I/flutter (30859): Image YResolution: 72
I/flutter (30859): Image ResolutionUnit: Pixels/Inch
I/flutter (30859): Image Software: HDR+ 1.0.748116481zdbh
I/flutter (30859): Image DateTime: 2025:06:07 12:58:46
I/flutter (30859): Image YCbCrPositioning: Centered
I/flutter (30859): Image ExifOffset: 220
I/flutter (30859): GPS GPSVersionID: [2, 2, 0, 0]
I/flutter (30859): GPS GPSLatitudeRef: N
I/flutter (30859): GPS GPSLatitude: [40, 8, 359/20]
I/flutter (30859): GPS GPSLongitudeRef: W
I/flutter (30859): GPS GPSLongitude: [82, 57, 1432/25]
I/flutter (30859): GPS GPSAltitudeRef: 0
I/flutter (30859): GPS GPSAltitude: 23619/100
I/flutter (30859): GPS GPSTimeStamp: [16, 58, 46]
I/flutter (30859): GPS GPSImgDirectionRef: M
I/flutter (30859): GPS GPSImgDirection: 116
I/flutter (30859): GPS GPSDate: 2025:06:07
I/flutter (30859): Image GPSInfo: 954
I/flutter (30859): Thumbnail Compression: JPEG (old-style)
I/flutter (30859): Thumbnail Orientation: Horizontal (normal)
I/flutter (30859): Thumbnail XResolution: 72
I/flutter (30859): Thumbnail YResolution: 72
I/flutter (30859): Thumbnail ResolutionUnit: Pixels/Inch
I/flutter (30859): Thumbnail JPEGInterchangeFormat: 1297
I/flutter (30859): Thumbnail JPEGInterchangeFormatLength: 27413
I/flutter (30859): EXIF ExposureTime: 719/1000000
I/flutter (30859): EXIF FNumber: 11/5
I/flutter (30859): EXIF ExposureProgram: Program Normal
I/flutter (30859): EXIF ISOSpeedRatings: 47
I/flutter (30859): EXIF ExifVersion: 0232
I/flutter (30859): EXIF DateTimeOriginal: 2025:06:07 12:58:46
I/flutter (30859): EXIF DateTimeDigitized: 2025:06:07 12:58:46
I/flutter (30859): EXIF OffsetTime: -04:00
I/flutter (30859): EXIF OffsetTimeOriginal: -04:00
I/flutter (30859): EXIF OffsetTimeDigitized: -04:00
I/flutter (30859): EXIF ComponentsConfiguration: YCbCr
I/flutter (30859): EXIF ShutterSpeedValue: 261/25
I/flutter (30859): EXIF ApertureValue: 57/25
I/flutter (30859): EXIF BrightnessValue: 881/100
I/flutter (30859): EXIF ExposureBiasValue: 0
I/flutter (30859): EXIF MaxApertureValue: 57/25
I/flutter (30859): EXIF SubjectDistance: 4294967295
I/flutter (30859): EXIF MeteringMode: CenterWeightedAverage
I/flutter (30859): EXIF Flash: Flash did not fire, compulsory flash mode
I/flutter (30859): EXIF FocalLength: 137/50
I/flutter (30859): EXIF SubSecTime: 502
I/flutter (30859): EXIF SubSecTimeOriginal: 502
I/flutter (30859): EXIF SubSecTimeDigitized: 502
I/flutter (30859): EXIF FlashPixVersion: 0100
I/flutter (30859): EXIF ColorSpace: sRGB
I/flutter (30859): EXIF ExifImageWidth: 2736
I/flutter (30859): EXIF ExifImageLength: 3648
I/flutter (30859): Interoperability InteroperabilityIndex: R98
I/flutter (30859): Interoperability InteroperabilityVersion: [48, 49, 48, 48]
I/flutter (30859): EXIF InteroperabilityOffset: 924
I/flutter (30859): EXIF SensingMethod: One-chip color area
I/flutter (30859): EXIF SceneType: Directly Photographed
I/flutter (30859): EXIF CustomRendered: Custom
I/flutter (30859): EXIF ExposureMode: Auto Exposure
I/flutter (30859): EXIF WhiteBalance: Auto
I/flutter (30859): EXIF DigitalZoomRatio: 0
I/flutter (30859): EXIF FocalLengthIn35mmFilm: 21
I/flutter (30859): EXIF SceneCaptureType: Standard
I/flutter (30859): EXIF Contrast: Normal
I/flutter (30859): EXIF Saturation: Normal
I/flutter (30859): EXIF Sharpness: Normal
I/flutter (30859): EXIF SubjectDistanceRange: 3
I/flutter (30859): EXIF LensMake: Google
I/flutter (30859): EXIF LensModel: Pixel 7 front camera 2.74mm f/2.2
I/flutter (30859): EXIF Tag 0xA460: 3
I/flutter (30859): JPEGThumbnail: 

Actual results

Location data is not shown when image is selected via camera

ImageSource.camera
I/flutter (30859): Path : /data/user/0/com.example.flutter_meta_data/cache/ecd788eb-3acc-49bb-b918-cef62c294e6c6308949658150860730.jpg
I/flutter (30859): Image ImageWidth: 4080
I/flutter (30859): Image ImageLength: 3072
I/flutter (30859): Image Make: Google
I/flutter (30859): Image Model: Pixel 7
I/flutter (30859): Image Orientation: Rotated 90 CW
I/flutter (30859): Image DateTime: 2025:06:07 20:01:21
I/flutter (30859): Image ExifOffset: 133
I/flutter (30859): EXIF ExposureTime: 13251/400000
I/flutter (30859): EXIF FNumber: 37/20
I/flutter (30859): EXIF ISOSpeedRatings: 385
I/flutter (30859): EXIF OffsetTime: -04:00
I/flutter (30859): EXIF ShutterSpeedValue: -491/100
I/flutter (30859): EXIF ApertureValue: 177/100
I/flutter (30859): EXIF SubjectDistance: 221/200
I/flutter (30859): EXIF Flash: Flash did not fire
I/flutter (30859): EXIF FocalLength: 681/100
I/flutter (30859): EXIF SubSecTime: 568
I/flutter (30859): EXIF ExifImageWidth: 4080
I/flutter (30859): EXIF ExifImageLength: 3072
I/flutter (30859): EXIF SubjectDistanceRange: 2

Code sample

Code sample
import 'dart:io';

import 'package:exif/exif.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter EXIF Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const ExifDemo(),
    );
  }
}

class ExifDemo extends StatefulWidget {
  const ExifDemo({Key? key}) : super(key: key);

  @override
  _ExifDemoState createState() => _ExifDemoState();
}

class _ExifDemoState extends State<ExifDemo> {
  XFile? _image;
  Map<String, dynamic>? _metadata;
  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      requestPermissions();
    });
    super.initState();
  }

  Future<void> requestPermissions() async {
    final status = await Permission.accessMediaLocation.request();
    if (status.isGranted) {
      print("Media location access granted");
    } else if (status.isDenied) {
      print("Media location access denied");
      // Optionally, you can show a dialog to inform the user about the denied permission
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: const Text(
              "Media location access denied. Please allow it in settings."),
          action: SnackBarAction(
            label: 'Settings',
            onPressed: () {
              openAppSettings();
            },
          ),
        ),
      );
    } else if (status.isPermanentlyDenied) {
      print("Media location access permanently denied");
      openAppSettings();
    } else {
      print("Media location access status: $status");
    }
  }

  Future<void> getImage({required bool isGallery}) async {
    ImagePicker picker = ImagePicker();
    XFile? pickedFile;

    try {
      pickedFile = isGallery
          ? await picker.pickImage(source: ImageSource.gallery)
          : await picker.pickImage(source: ImageSource.camera);
    } on PlatformException catch (error) {
      switch (error.code.toLowerCase()) {
        case 'photo_access_denied':
          print(error.code);
          break;
        case 'camera_access_denied':
          print(error.code);
          break;
        default:
          print(error.code);
          break;
      }
    } catch (error) {
      print(error);
    }

    if (pickedFile != null) {
      setState(() {
        _image = pickedFile;
        _metadata = null;
      });
      await readExifData();
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => ImageExifData(
            metadata: _metadata,
            image: _image,
          ),
        ),
      );
    }
  }

  Future<void> readExifData() async {
    if (_image != null) {
      final _imageBytes = File(_image!.path).readAsBytesSync();
      final exifData = await readExifFromBytes(_imageBytes);

      setState(() {
        _metadata = exifData;
      });
      if (_metadata!.isEmpty) {
        print("No EXIF information found");
        return;
      }

      print('Path : ${_image!.path}');
      for (final entry in _metadata!.entries) {
        print("${entry.key}: ${entry.value}");
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () {
                  getImage(isGallery: false);
                },
                child: const Icon(
                  Icons.camera,
                  size: 25,
                ),
              ),
              const SizedBox(width: 20),
              ElevatedButton(
                onPressed: () {
                  getImage(isGallery: true);
                },
                child: const Icon(
                  Icons.photo_library_rounded,
                  size: 25,
                ),
              ),
            ],
          ),
        ),
      ),
    ));
  }
}

class ImageExifData extends StatelessWidget {
  final Map<String, dynamic>? metadata;
  final XFile? image;
  const ImageExifData({super.key, this.metadata, this.image});

  Widget _buildMetadataList() {
    if (metadata == null) {
      return Container(); // Return an empty container if no metadata available
    }

    List<Widget> metadataWidgets = [];

    metadata!.forEach((key, value) {
      metadataWidgets.add(
        ListTile(
          title: Text(key),
          subtitle: Text(value.toString()),
        ),
      );
    });

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: metadataWidgets,
    );
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Column(
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 8.0),
              child: SizedBox(
                width: double.infinity,
                child: ElevatedButton(
                  onPressed: () {
                    Navigator.pop(context);
                  },
                  child: const Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.refresh, size: 20),
                      SizedBox(width: 10),
                      Text('Retake Image'),
                    ],
                  ),
                ),
              ),
            ),
            Expanded(
              child: SingleChildScrollView(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    if (image != null)
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Column(
                          children: [
                            Text(
                              'Image Path: ${image!.path}',
                              style: const TextStyle(fontSize: 16),
                            ),
                            Card(
                              shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(0.0),
                              ),
                              elevation: 5,
                              margin: const EdgeInsets.all(10),
                              child: Stack(children: [
                                Image.file(
                                  File(image!.path),
                                  fit: BoxFit.fill,
                                ),
                              ]),
                            ),
                          ],
                        ),
                      ),
                    const Text(
                      'Image EXIF Data',
                      style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 10),
                    _buildMetadataList(),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

I am not using latest version of flutter but that shouldn't matter here, I am using latest version of image_picker

Doctor output
[!] Flutter (Channel [user-branch], 3.19.6, on macOS 15.5 24F74 darwin-arm64, locale en-US)
    ! Flutter version 3.19.6 on channel [user-branch] at /Users/maheshjamdade/Development/flutter
      Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
      If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/docs/get-started/install.
    ! Upstream repository unknown source is not a standard remote.
      Set environment variable "FLUTTER_GIT_URL" to unknown source to dismiss this error.
    • Framework revision 54e66469a9 (1 year, 2 months ago), 2024-04-17 13:08:03 -0700
    • Engine revision c4cd48e186
    • Dart version 3.3.4
    • DevTools version 2.31.1
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.1)
    • Android SDK at /Users/maheshjamdade/Library/Android/sdk
    • Platform android-35, build-tools 35.0.1
    • Java binary at: /Users/maheshjamdade/Library/Java/JavaVirtualMachines/ms-17.0.15/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment Microsoft-11369864 (build 17.0.15+6-LTS)
    • All Android licenses accepted.

[!] Xcode - develop for iOS and macOS (Xcode 16.4)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16F6
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.6+-13368085-b895.109)

[✓] VS Code (version 1.100.2)
    • VS Code at /Users/maheshjamdade/Downloads/Visual Studio Code.app/Contents
    • Flutter extension version 3.112.0

[✓] Connected device (3 available)
    • Pixel 7 (mobile) • 192.168.40.6:5533 • android-arm64  • Android 15 (API 35)
    • macOS (desktop)  • macos             • darwin-arm64   • macOS 15.5 24F74 darwin-arm64
    • Chrome (web)     • chrome            • web-javascript • Google Chrome 137.0.7151.69

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 2 categories.

cc: @gmackall if you have any insights

Metadata

Metadata

Assignees

No one assigned

    Labels

    in triagePresently being triaged by the triage teamwaiting for customer responseThe Flutter team cannot make further progress on this issue until the original reporter responds

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions