Cómo guardar coordenadas GPS en datos exif en Android?

Estoy escribiendo coordenadas GPS a mi imagen JPEG, y las coordenadas son correctas (como lo demuestra mi salida logcat), pero parece que está siendo dañado de alguna manera. La lectura de los datos exif da como resultado valores nulos o, en el caso de mi GPS: 512.976698 degrees, 512.976698 degrees . ¿Puede alguien arrojar algo de luz sobre este problema?

Escribiéndolo

  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(); } 

Y leerlo:

  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(); } 

Se 37.715183 (por ejemplo) 37.715183 , -117.260489 y sale 33619970/65540, 14811136/3368550 , 33619970/65540, 14811136/3368550 . ¿Lo estoy haciendo mal?

EDITAR:

Por lo tanto, el problema es que no estoy codificándolo en el formato correctamente definido, que es algo como lo que ves aquí:

Introduzca aquí la descripción de la imagen

¿Puede alguien explicar cuál es este formato? Obviamente el primer número es 22/1 = 22 grados, pero no puedo calcular cómo calcular el decimal allí.

GPSLatitud

Indica la latitud. La latitud se expresa como tres valores RATIONAL que dan los grados, minutos y segundos, respectivamente. Si la latitud se expresa en grados, minutos y segundos, un formato típico sería dd/1,mm/1,ss/1 . Cuando se usan grados y minutos y, por ejemplo, se dan fracciones de minutos hasta dos decimales, el formato sería dd/1,mmmm/100,0/1 .

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

Los documentos Android especifican esto sin explicación: http://developer.android.com/reference/android/media/ExifInterface.html#TAG_GPS_LATITUDE

Los datos Exif se estandarizan y los datos GPS deben codificarse utilizando las coordenadas geográficas (minutos, segundos, etc.) descritas anteriormente en lugar de una fracción. A menos que esté codificado en ese formato en la etiqueta exif, no se pegará.

Cómo codificar: http://en.wikipedia.org/wiki/Geographic_coordinate_conversion

Cómo decodificar: http://android-er.blogspot.com/2010/01/convert-exif-gps-info-to-degree-format.html

Aquí hay un código que he hecho para geotag mis imágenes. No está probado pesadamente todavía, pero parece ser aceptable (editor de JOSM y la localización leída del exiftool). Comentarios apreciados.

 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(); 

Y la clase GPS está aquí. (El método podría ser más corto, pero es legible al menos)

 /* * @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(); } } 

Otras respuestas entregadas información de fondo agradable e incluso un ejemplo. Esto no es una respuesta directa a la pregunta, pero me gustaría añadir un ejemplo aún más simple sin la necesidad de hacer ninguna matemática. La clase Location ofrece una función de conversión agradable:

 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"; } 

Almacé el valor de retorno en mi imagen y la etiqueta se analiza bien. Puedes comprobar tu imagen y las coordenadas geográficas aquí: http://regex.info/exif.cgi

Editar

@ratanas comentario traducido al código:

 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; } 

Estos son algunos buenos conversores LatLong : latlong.net

Compruebe el código fuente de Android: https://android.googlesource.com/platform/frameworks/base/+/android-4.4.2_r2/core/java/android/hardware/Camera.java

/ ** * Establece la coordenada de longitud de GPS. Esto se almacenará en la cabecera JPEG EXIF ​​*. * * @param longitude Coordenada de longitud de GPS. * / Public void setGpsLongitude (longitud doble) {set (KEY_GPS_LONGITUDE, Double.toString (longitude)); }

Así que es una impresión directa, mi registro también lo admite: ExifInterface.TAG_GPS_LONGITUDE: -121.0553966

Mi conclusión es establecer que la impresión directa está bien.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.