Невозможно установить тег Date Taken / DateTime с помощью ExifInterface в Android

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

То, что я пытаюсь сделать, это установить тег Date Taken (Tag_DateTime) в данные Exif JPEG из приложения Android. У меня уже есть рабочий код для установки тегов Latitude и Longitute, но я не могу на всю жизнь получить тег Date, который нужно установить.

Вот код:

SimpleDateFormat fmt_Exif = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss"); try { ExifInterface exif = new ExifInterface(filePhoto.getPath()); // Set and save the GPS and time data exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, strLat); exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, strLong); exif.setAttribute(ExifInterface.TAG_DATETIME, fmt_Exif.format(locLatestLocation.getTime())); exif.saveAttributes(); } catch (IOException e) { e.printStackTrace(); } 
  • LocLatestLocation – Location используется для получения времени в миллисекундах.
  • Fmt_Exif – SimpleDateFormat используется для форматирования миллисекундного времени в правильном формате для тега TAG_DateTime Exif.
  • StrLat & strLong – Настраивается в другом месте в правильном формате для установки тегов широты и долготы.

Я где-то читал, что тег должен быть записан в миллисекундах, поэтому попробовал это тоже безрезультатно. Чтобы подтвердить мое форматирование на том, что на самом деле хранится, я прочитал и вывел неформатированный тег из файла jpeg с тегом Date Taken, но результат находится в том же формате, что и то, что я пишу в теге, и его все еще не работает.

Также стоит отметить, что я рассматриваю класс Sanselan для этого, и из-за сложности и отсутствия примеров гораздо лучше попытаться заставить мое существующее решение работать, прежде чем перейти на совершенно другой.

Кто-нибудь смог это сделать, и если да, то что я делаю неправильно?

Android ExifInterface, досадно, молча отбрасывает любые данные, которые он считает недействительными. Хуже того, в документации даже не упоминается, какие действительные значения могут быть.

Я также обнаружил, что если вы укажете атрибут EXIF, который Android не может определить (IE: он не является константой TAG_ ExifInterface), он также полностью игнорирует его, а также терпит неудачу.

Мне нужно было то же самое сейчас. Я прочитал эту статью EXIF ​​из MIT, и я TAG_DATETIME :

 exif.setAttribute(ExifInterface.TAG_DATETIME,"2013:06:21 00:00:07"); exif.setAttribute(ExifInterface.TAG_GPS_DATESTAMP,"2013:06:21"); exif.setAttribute(ExifInterface.TAG_GPS_TIMESTAMP,"00:00:07"); 

Это выглядело так:

Exif 1

Exif 2

Обратите внимание, что это только в разделах EXIF ​​/ TIFF и GPS, а не фактические отметки времени оригинала и оцифровки:

Exif 3

Я также хотел изменить оригинальные и оцифрованные временные метки, поэтому попробовал библиотеку JHeader :

 try { JpegHeaders headers = new JpegHeaders(FakeBurst.PICTURE_PATH); App1Header app1Header = headers.getApp1Header(); app1Header.setValue(new TagValue(Tag.IMAGEDESCRIPTION,"bla bla bla")); app1Header.setValue(new TagValue(Tag.DATETIMEORIGINAL,"2013:06:21 00:00:07")); app1Header.setValue(new TagValue(Tag.DATETIMEDIGITIZED,"2013:06:21 00:00:07")); headers.save(true); System.out.println(this+" wrote exif timestamp"); } catch (Exception e) { e.printStackTrace(); } 

С добавленным в onCreate :

 JpegHeaders.preheat(); 

И это сработало:

Exif 4

Exif 5

Я вижу этот пост с декабря, поэтому, возможно, код Android ExifInterface, который я опубликовал выше, не работал с этой версией SDK, но я предполагаю, что подход библиотеки JHeader будет работать.

У меня с вами такая же проблема. Когда я пытаюсь использовать TAG_DATETIME для сохранения принятой даты, это не сработает, и исходное значение take_date было потеряно. Я действительно не знаю разницы между функцией @hide getDateTime () и getGpsDateTime (). Кажется, дата getGpsDateTime (). И я попробую TAG_GPS_DATESTAMP и TAG_GPS_TIMESTAMP.

 /** * Returns number of milliseconds since Jan. 1, 1970, midnight UTC. * Returns -1 if the date time information if not available. * @hide */ public long getGpsDateTime() { String date = mAttributes.get(TAG_GPS_DATESTAMP); String time = mAttributes.get(TAG_GPS_TIMESTAMP); if (date == null || time == null) return -1; String dateTimeString = date + ' ' + time; if (dateTimeString == null) return -1; ParsePosition pos = new ParsePosition(0); try { Date datetime = sFormatter.parse(dateTimeString, pos); if (datetime == null) return -1; return datetime.getTime(); } catch (IllegalArgumentException ex) { return -1; } } 

Вы можете попробовать так же, как в ExifInterface.java

 private static SimpleDateFormat sFormatter; static { sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss"); sFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); } 

И затем обновить:

 exif.setAttribute(ExifInterface.TAG_DATETIME, sFormatter.format(new Date(System.currentTimeMillis()))); 
 SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss"); exifInterface.setAttribute("DateTimeOriginal", dateTimeFormat.format(date)); exifInterface.setAttribute("DateTimeDigitized", dateTimeFormat.format(date)); 

Это работает для меня (по крайней мере, API уровня 14+)

Я столкнулся с проблемой, что изображения от Nexus 6 и Lumia 935 не имеют полей CreateDate и DateTimeOriginal .

Телефон Android и Windows сохранит метку времени также на имени файла IMG_20160320_145825.jpg WP_20160328_13_40_42_Pro.jpg

Мне удастся исправить эту проблему и добавить поле, в котором выполняется этот скрипт:

 #! /bin/bash COUNTER=0 for filename in ./* do case "$filename" in *.JPG|*.jpeg|*.jpg) COUNTER=$[$COUNTER +1] y=${filename:6:4} M=${filename:10:2} d=${filename:12:2} H=${filename:15:2} m=${filename:17:2} s=${filename:19:2} echo "'"$y":"$M":"$d $H":"$m":"$s"'" " --> "$filename exiftool -v2 -AllDates="'"$y":"$M":"$d" "$H":"$m":"$s"'" -overwrite_original $filename ;; *) echo $filename 'Not a *.jpg' ;; esac done echo $COUNTER "files updated" 

Я надеюсь, что это поможет кому-то