Как сохранить GPS-координаты в данных exif на Android?

Я пишу GPS-координаты для своего изображения в формате JPEG, и координаты правильны (как показывает мой вывод logcat), но похоже, что он каким-то образом поврежден. Чтение данных exif приводит либо к нулевым значениям, либо, в случае моего GPS: 512.976698 degrees, 512.976698 degrees . Может ли кто-нибудь пролить свет на эту проблему?

Написав:

  try { ExifInterface exif = new ExifInterface(filename); exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, latitude); exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, longitude); exif.saveAttributes(); Log.e("LATITUDE: ", latitude); Log.e("LONGITUDE: ", longitude); } catch (IOException e) { e.printStackTrace(); } 

И читая его:

  try { ExifInterface exif = new ExifInterface("/sdcard/globetrotter/mytags/"+ TAGS[position]); Log.e("LATITUDE EXTRACTED", exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE)); Log.e("LONGITUDE EXTRACTED", exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE)); } catch (IOException e) { e.printStackTrace(); } 

Он входит (например) 37.715183 , -117.260489 и выходит 33619970/65540, 14811136/3368550 , 33619970/65540, 14811136/3368550 . Я делаю это неправильно?

РЕДАКТИРОВАТЬ:

Итак, проблема в том, что я не кодирую его в правильно определенном формате, что вы видите здесь:

Введите описание изображения здесь

Может ли кто-нибудь объяснить, что это за формат? Очевидно, первое число 22/1 = 22 градуса, но я не могу понять, как вычислить десятичную точку там.

Solutions Collecting From Web of "Как сохранить GPS-координаты в данных exif на Android?"

GPSLatitude

Указывает широту. Широта выражается в виде трех значений RATIONAL дающих соответственно градусы, минуты и секунды. Если широта выражается в градусах, минутах и ​​секундах, типичным форматом будет dd/1,mm/1,ss/1 . Когда используются градусы и минуты и, например, долей минут дается до двух знаков после запятой, формат будет dd/1,mmmm/100,0/1 .

https://docs.google.com/viewer?url=http%3A%2F%2Fwww.exif.org%2FExif2-2.PDF

В документах Android указано это без объяснений: http://developer.android.com/reference/android/media/ExifInterface.html#TAG_GPS_LATITUDE

Данные Exif стандартизированы, а данные GPS должны кодироваться с использованием географических координат (минут, секунд и т. Д.), Описанных выше, а не доли. Если он не закодирован в этом формате в теге exif, он не будет вставляться.

Как закодировать: http://en.wikipedia.org/wiki/Geographic_coordinate_conversion

Как декодировать: http://android-er.blogspot.com/2010/01/convert-exif-gps-info-to-degree-format.html

Вот какой код я сделал для геотаг моих фотографий. Это еще не проверено, но, похоже, все в порядке (редактор JOSM и место для чтения exiftool). Обратная связь оценена.

 ExifInterface exif = new ExifInterface(filePath.getAbsolutePath()); exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, GPS.convert(latitude)); exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, GPS.latitudeRef(latitude)); exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, GPS.convert(longitude)); exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, GPS.longitudeRef(longitude)); exif.saveAttributes(); 

И класс GPS здесь. (Метод может быть короче, но, по крайней мере, доступен для чтения)

 /* * @author fabien */ public class GPS { private static StringBuilder sb = new StringBuilder(20); /** * returns ref for latitude which is S or N. * @param latitude * @return S or N */ public static String latitudeRef(double latitude) { return latitude<0.0d?"S":"N"; } /** * returns ref for latitude which is S or N. * @param latitude * @return S or N */ public static String longitudeRef(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 */ synchronized public static final String convert(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); sb.setLength(0); sb.append(degree); sb.append("/1,"); sb.append(minute); sb.append("/1,"); sb.append(second); sb.append("/1000,"); return sb.toString(); } } 

Другие ответы доставили приятную справочную информацию и даже пример. Это не прямой ответ на вопрос, но я хотел бы добавить еще более простой пример без необходимости делать математику. Класс Location обеспечивает приятную функцию преобразования :

 public String getLonGeoCoordinates(Location location) { if (location == null) return "0/1,0/1,0/1000"; // You can adapt this to latitude very easily by passing location.getLatitude() String[] degMinSec = Location.convert(location.getLongitude(), Location.FORMAT_SECONDS).split(":"); return degMinSec[0] + "/1," + degMinSec[1] + "/1," + degMinSec[2] + "/1000"; } 

Я сохранил возвращаемое значение в моем изображении, и тег разбирается отлично. Вы можете проверить свое изображение и геокоординаты внутри: http://regex.info/exif.cgi

редактировать

Комментарий @ratanas, переведенный в код:

 public boolean storeGeoCoordsToImage(File imagePath, Location location) { // Avoid NullPointer if (imagePath == null || location == null) return false; // If we use Location.convert(), we do not have to worry about absolute values. try { // c&p and adapted from @Fabyen (sorry for being lazy) ExifInterface exif = new ExifInterface(imagePath.getAbsolutePath()); exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, getLatGeoCoordinates(location)); exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, location.getLatitude() < 0 ? "S" : "N"); exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, getLonGeoCoordinates(location)); exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, location.getLongitude() < 0 ? "W" : "E"); exif.saveAttributes(); } catch (IOException e) { // do something return false; } // Data was likely written. For sure no NullPointer. return true; } 

Вот несколько хороших конвертеров LatLong : latlong.net

Проверить исходный код Android: https://android.googlesource.com/platform/frameworks/base/+/android-4.4.2_r2/core/java/android/hardware/Camera.java

/ ** * Устанавливает координату долготы GPS. Это будет сохранено в заголовке JPEG EXIF ​​*. * * @param долгота координата долготы GPS. * / Public void setGpsLongitude (двойная долгота) {set (KEY_GPS_LONGITUDE, Double.toString (долгота)); }

Так что это прямая печать, мой журнал также поддерживает ее: ExifInterface.TAG_GPS_LONGITUDE: -121.0553966

Мое заключение заключается в том, чтобы установить его, поскольку прямая печать в порядке.