Handling exif data in android

Hi all, in this article I am going to explain about reading and writing metadata or exif data of a captured image in Android devices. This will help you all to understand that we can analyse any captured image based on their exif data which will not need any expertise in image processing. Before start let me clear that this article is for Android developers who are familiar with Android Api’s.

What is EXIF ?

Exif stands for Exchangeable Image File Format. Exif contains loads of data about phone, camera, camera settings and possible copyright information when you capture an image by default but it is not limited to this and we can even add additional information as per our need.

Read also – How to make your app Marshmallow ready

What data EXIF supports ?

As I already mentioned in above paragraph, Exif support data related to phone, camera, camera settings and might be copyright information. Here is the more precise list of information it can contains in an image captured from Android device –

  • Image length, Image width, Capture data and time, Device manufacturer, Device model, Orientation, White balance, Focal length, Flash, Latitude and longitude
  • UserComment

These are self- explanatory.  I have added “UserComment” in a separate bullet to differentiate its purpose.  “UserComment” is a key in exif can be used to add any sort of additional information on images captured from an app.

Read EXIF data in Android

Here is the code to read standard data from an image.

     * @param fileNameWithPath
     * @return all image exif attributes in bundle
    public static Bundle getImageAttributes(String fileNameWithPath) {
        Bundle exifBundle = new Bundle();
        try {
            String latitudeRef, longitudeRef;
            Float latitude, longitude;

            ExifInterface exifInterface = new ExifInterface(fileNameWithPath);

            latitudeRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);

            if (latitudeRef.equals("N")) {
                latitude = convertFromDegreeMinuteSeconds(exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
            } else {
                latitude = 0 - convertFromDegreeMinuteSeconds(exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE));

            longitudeRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
            if (longitudeRef.equals("E")) {
                longitude = convertFromDegreeMinuteSeconds(exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
            } else {
                longitude = 0 - convertFromDegreeMinuteSeconds(exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));

            exifBundle.putString(ExifInterface.TAG_IMAGE_LENGTH, exifInterface.getAttribute(ExifInterface.TAG_IMAGE_LENGTH));
            exifBundle.putString(ExifInterface.TAG_IMAGE_WIDTH, exifInterface.getAttribute(ExifInterface.TAG_IMAGE_WIDTH));
            exifBundle.putString(ExifInterface.TAG_DATETIME, exifInterface.getAttribute(ExifInterface.TAG_DATETIME));
            exifBundle.putString(ExifInterface.TAG_MAKE, exifInterface.getAttribute(ExifInterface.TAG_MAKE));
            exifBundle.putString(ExifInterface.TAG_MODEL, exifInterface.getAttribute(ExifInterface.TAG_MODEL));
            exifBundle.putString(ExifInterface.TAG_ORIENTATION, exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION));
            exifBundle.putString(ExifInterface.TAG_WHITE_BALANCE, exifInterface.getAttribute(ExifInterface.TAG_WHITE_BALANCE));
            exifBundle.putString(ExifInterface.TAG_FOCAL_LENGTH, exifInterface.getAttribute(ExifInterface.TAG_FOCAL_LENGTH));
            exifBundle.putString(ExifInterface.TAG_FLASH, exifInterface.getAttribute(ExifInterface.TAG_FLASH));
            exifBundle.putString(ExifInterface.TAG_GPS_PROCESSING_METHOD, exifInterface.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD));
            exifBundle.putString(ExifInterface.TAG_GPS_DATESTAMP, exifInterface.getAttribute(ExifInterface.TAG_GPS_DATESTAMP));
            exifBundle.putString(ExifInterface.TAG_GPS_TIMESTAMP, exifInterface.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP));
            exifBundle.putString(ExifInterface.TAG_GPS_LATITUDE, String.valueOf(latitude));
            exifBundle.putString(ExifInterface.TAG_GPS_LATITUDE_REF, latitudeRef);
            exifBundle.putString(ExifInterface.TAG_GPS_LONGITUDE, String.valueOf(longitude));
            exifBundle.putString(ExifInterface.TAG_GPS_LONGITUDE_REF, longitudeRef);

        } catch (IOException e) {
        return exifBundle;

The above method will return a Bundle of all the standard EXIF data which you can use for any kind of analysis. It is using an additional method to convert back latitude and longitude from degree, minutes, seconds i.e.,

private static Float convertFromDegreeMinuteSeconds(String stringDMS) {
        Float result = null;
        String[] DMS = stringDMS.split(",", 3);

        String[] stringD = DMS[0].split("/", 2);
        Double D0 = Double.valueOf(stringD[0]);
        Double D1 = Double.valueOf(stringD[1]);
        Double FloatD = D0 / D1;

        String[] stringM = DMS[1].split("/", 2);
        Double M0 = Double.valueOf(stringM[0]);
        Double M1 = Double.valueOf(stringM[1]);
        Double FloatM = M0 / M1;

        String[] stringS = DMS[2].split("/", 2);
        Double S0 = Double.valueOf(stringS[0]);
        Double S1 = Double.valueOf(stringS[1]);
        Double FloatS = S0 / S1;

        result = (float) (FloatD + (FloatM / 60) + (FloatS / 3600));
        return result;

 Write EXIF data in Android

Writing metadata is little tricky as it has only one key(“UserComment”) for custom data, so I decided to convert all additional data into json string and store that under “UserComment” tag. Let have a look into it –

public static void saveExif(String fileNameWithPath, Bundle extraInfo) throws IOException {
       if (extraInfo != null) {
           ExifInterface exif = new ExifInterface(fileNameWithPath);

           for (String key : extraInfo.keySet()) {
               Object obj = extraInfo.get(key);
               if (obj instanceof Location) {
                   Location location = (Location) obj;
                   exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, convertToDegreeMinuteSeconds(location.getLatitude()));
                   exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, getLatitudeRef(location.getLatitude()));
                   exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, convertToDegreeMinuteSeconds(location.getLongitude()));
                   exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, getLongitudeRef(location.getLongitude()));

           JSONObject json = new JSONObject();
           Set<String> keys = extraInfo.keySet();
           for (String key : keys) {
               try {
                       json.put(key, extraInfo.get(key));
               } catch (JSONException e) {
                   //Handle exception here

           exif.setAttribute("UserComment", json.toString());

    * returns ref for latitude which is S or N.
    * @param latitude
    * @return S or N
   private static String getLatitudeRef(double latitude) {
       return latitude < 0.0d ? "S" : "N";

    * returns ref for latitude which is S or N.
    * @param longitude
    * @return W or E
   private static String getLongitudeRef(double longitude) {
       return longitude < 0.0d ? "W" : "E";

    * convert latitude into DMS (degree minute second) format. For instance<br/>
    * -79.948862 becomes<br/>
    * 79/1,56/1,55903/1000<br/>
    * It works for latitude and longitude<br/>
    * @param latitude could be longitude.
    * @return
   private static String convertToDegreeMinuteSeconds(double latitude) {
       latitude = Math.abs(latitude);
       int degree = (int) latitude;
       latitude *= 60;
       latitude -= (degree * 60.0d);
       int minute = (int) latitude;
       latitude *= 60;
       latitude -= (minute * 60.0d);
       int second = (int) (latitude * 1000.0d);

       StringBuilder sb = new StringBuilder();
       return sb.toString();

In this above code I am passing all data into bundle and then first writing location data against location tags where as converting entire data into a single json string and writing under “UserComment” tag. After writing the custom data it comes under “UserComment” tag.

Once you are done with writing you can check whether data has been written correctly or not by using any online available tools like – metapicz.com .

To know more check this out .

I hope this article will be helpful for all of you who are playing with images, do not forget to share it with your friends.

Happy coding!!!

Leave a Reply

Your email address will not be published. Required fields are marked *