1

I have an app published on Google Play, which at some point fetches the users geographical location and saves it with a picture. I have however now gotten reports from a few Brazilian users complaining about the pictures are getting GeoTagged in Saudi Arabia. Have only gotten this complaint from users in Brazil and I am by no means what so ever able to reproduce the issue myself.

What could be causing this?

// I save and read the location in an ExifInterface with this "book"..

// Write Geotag and time to Image's Exif public Boolean writeExifData(Location location, Date date, String filepath){ // Determine if we got a location boolean isLocationOn = false; if(location != null){ isLocationOn = true; } try { // Set up exif ExifInterface exif = new ExifInterface(filepath); if(isLocationOn){ // Get location values double latitude = location.getLatitude(); double longitude = location.getLongitude(); float accuracy = location.getAccuracy(); // Convert Latitude and Longitude int num1Lat = (int)Math.floor(latitude); int num2Lat = (int)Math.floor((latitude - num1Lat) * 60); double num3Lat = (latitude - ((double)num1Lat+((double)num2Lat/60))) * 3600000; int num1Lon = (int)Math.floor(longitude); int num2Lon = (int)Math.floor((longitude - num1Lon) * 60); double num3Lon = (longitude - ((double)num1Lon+((double)num2Lon/60))) * 3600000; exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, num1Lat+"/1,"+num2Lat+"/1,"+num3Lat+"/1000"); exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, num1Lon+"/1,"+num2Lon+"/1,"+num3Lon+"/1000"); if (latitude > 0) { exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "N"); }else { exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "S"); } if (longitude > 0) { exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "E"); }else { exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "W"); } // Add accuracy to exif String accuracy_value = String.valueOf(Math.round(accuracy)); exif.setAttribute("UserComment", "accuracy=" + accuracy_value); } // Add capture time to exif exif.setAttribute(ExifInterface.TAG_DATETIME, date.toString()); // Save exif exif.saveAttributes(); Log.v(Constants.TAG_ALERT_PROCESS, "Wrote data to Exif successfully"); return true; } catch (IOException e) { Log.v(Constants.TAG_ALERT_PROCESS, "Failed writing data to Exif with error: " + e.getMessage()); return false; } } public Object_ImageExifData readExifData(String filePath){ Helper_ExifGeoConverter geoConverter; Location location = null; ExifInterface exif; // Format filePath String (remove "file://" ) if(filePath.startsWith("file://")){ filePath = filePath.replace("file://", ""); } try { exif = new ExifInterface(filePath); if(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE) != null){ geoConverter = new Helper_ExifGeoConverter(exif); location = new Location(""); float float_lat = geoConverter.getLatitude(); location.setLatitude(float_lat); float float_lon = geoConverter.getLongitude(); location.setLongitude(float_lon); /** Get accuracy. Accuracy is stored * under the tag UserComment as "accuracy=xx"*/ if(exif.getAttribute("UserComment") != null){ String value = exif.getAttribute("UserComment"); value = value.replace("accuracy=", ""); float accuracy = Integer.parseInt(value); location.setAccuracy(accuracy); } // Get capture time String time = ""; if(exif.getAttribute(ExifInterface.TAG_DATETIME) != null){ time = exif.getAttribute(ExifInterface.TAG_DATETIME); } return new Object_ImageExifData(location, time); }else{ // Get capture time String time = "xx.xx.xxxx"; if(exif.getAttribute(ExifInterface.TAG_DATETIME) != null){ time = exif.getAttribute(ExifInterface.TAG_DATETIME); } return new Object_ImageExifData(location, time); } } catch (IOException e) { e.printStackTrace(); Log.v("myTag", "Failed to read exif data"); return null; } } public class Helper_ExifGeoConverter{ private boolean valid = false; Float Latitude, Longitude; Helper_ExifGeoConverter(ExifInterface exif) { String attrLATITUDE = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE); String attrLATITUDE_REF = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF); String attrLONGITUDE = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE); String attrLONGITUDE_REF = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF); if ((attrLATITUDE != null) && (attrLATITUDE_REF != null) && (attrLONGITUDE != null) && (attrLONGITUDE_REF != null)) { valid = true; if (attrLATITUDE_REF.equals("N")) { Latitude = convertToDegree(attrLATITUDE); } else { Latitude = 0 - convertToDegree(attrLATITUDE); } if (attrLONGITUDE_REF.equals("E")) { Longitude = convertToDegree(attrLONGITUDE); } else { Longitude = 0 - convertToDegree(attrLONGITUDE); } } } private Float convertToDegree(String stringDMS){ Float result; 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 = new Float(FloatD + (FloatM/60) + (FloatS/3600)); return result; } 

SOLUTION With the help of @greenapps I came to realize that I was, when writing to Exif, converting location from decimal format to degrees, minutes, seconds format falsely. Used this code instead.

5
  • I couldn't see the line causing this error but just in case you didn't notice, (-23.548405, -46.640618) in Brazil and (23.548405, 46.640618) in Saudi Arabia, for example. You got any other complaints form that continent? I don't see any location manipulation here, maybe when saving it to the database, you take the absolute value or something like that. Commented Jul 5, 2014 at 12:35
  • huh, good spot - would be a good explanation. But, if this is the case (I somehow use the absolute value instead), no users in any negative coordinated area (or how to put it) would get a correct location. Which I'm pretty sure is not what's happening. Now I live on like 55,12 so I wouldn't know for sure, but I haven't gotten any complaints about this from people besides Brazil. Commented Jul 5, 2014 at 12:47
  • I have never used that feature but I know in AVD, we have the option to simulate any coordinates we like. Then, you might be able to debug your code. Look at this page htmlgoodies.com/beyond/mobile/… Commented Jul 5, 2014 at 13:42
  • Perfect, you are just thinking way faster that me - you can do the same on device with MockLocation apps, hope I'll track the bug down, thanks Commented Jul 5, 2014 at 13:45
  • 1
    I'm not, believe me. It's just a couple of sad experiences :) I'm glad they are of some use now. Commented Jul 5, 2014 at 13:48

1 Answer 1

0

If you put geo lat/lon tags in the exif info of a jpg then all lat/lons are positive. You also have to set a E/O and N/S tag. Are you doing that?

Sign up to request clarification or add additional context in comments.

12 Comments

Yes, I am saving it in exif as hours, minutes, seconds format
Sorry but that is no answer to my question. Reread again please.
Oh, excuse me, misunderstood. I am not quite sure what you mean by E/O, N/S tags - but I added the conversion/exif save and read code to the question
That is an incorrect viewer as it only is allowed to contain positive values for degrees/minutes/seconds. If you put in those negative values the viewer should not have shown them as negative but should have interpreted as unsigned. That would have given a very different value. Use another program/app to test.
Advice: first do the writing and check with external app if you put a good exif geo tag. You can also upload pictures to online services who then show the location on a map. After that implement the reading. IrfanView is good also. And as said before: at reading there should not be negative values. So removing a "-" is complete nonsense. Don't write negative values to begin with.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.