在Android中使用ExifInterface无法设置拍摄日期/时间标签

7

我已经研究并尝试了许多选项来尝试让这个工作,但很遗憾一直没有进展。

我正在尝试从Android应用程序中设置JPEG的Exif数据中的拍摄日期标签(Tag_DateTime)。 我已经有了可用于设置纬度和经度标签的工作代码,但是我无法设置拍摄日期标签。

以下是代码:

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 - 用于获取毫秒时间的位置。
  • fmt_Exif - SimpleDateFormat 用于将毫秒时间格式化为 TAG_DateTime Exif 标签所需的正确格式。
  • strLat & strLong - 在其他地方以正确的格式填充,以设置纬度和经度标签。

我在某个帖子中读到,该标签需要以毫秒格式编写,因此我也尝试过这种方法,但没有成功。为了确认我的格式与实际存储的格式相同,我从具有“拍摄日期”标签的 jpeg 文件中读取并输出了未格式化的标签,但输出格式与我写入标签的格式完全相同,仍然无法工作。

还值得一提的是,我已经研究了 Sanselan 类来完成此操作,由于其复杂性和缺乏示例,我更愿意尝试让现有解决方案正常工作,而不是完全改变成一个全新的解决方案。

如果有人成功完成了这个任务,请告诉我我做错了什么??


你找到任何解决方案了吗?如果我尝试设置“DateTime”字段,在保存后EXIF数据中会出现两个这样的字段... - pbu
7个回答

9

Android的ExifInterface会自动丢弃任何它认为无效的数据,这实在是令人恼火。更糟糕的是,文档中甚至没有提到哪些值是有效的。

我还发现,如果您指定了一个Android无法识别的EXIF属性(即它不是ExifInterface的TAG_常量之一),它也将完全忽略它,并且也会悄无声息地失败。


8

我刚刚也需要做同样的事情。 我读了这篇来自MIT的EXIF文章并获得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

我看到这篇文章是在去年12月发布的,所以也许我上面发布的Android ExifInterface代码无法与该SDK版本一起使用,但我猜JHeader库的方法应该能行。


2

我和你遇到了同样的问题。当我尝试使用TAG_DATETIME来保存拍摄日期时,它无法工作,并且原始的拍摄日期已经丢失。我真的不知道getDateTime()和getGpsDateTime()的@hide函数之间的区别。似乎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;
    }
}

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

0
SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");

exifInterface.setAttribute("DateTimeOriginal", dateTimeFormat.format(date));
exifInterface.setAttribute("DateTimeDigitized", dateTimeFormat.format(date));

对我来说可以(至少API级别14+)


0
如果您使用JodaTime库,我的示例可能对您有用。 请注意,根据文档GPS_TIMESTAMP需要UTC格式(不带本地偏移)。
如果所有字段都为空,则它适用于所有字段。
val exif = ExifInterface(file.path)
val dateTime = DateTime.now()
val dateTimeStr = dateTime.toString(DateTimeFormat.forPattern("yyyy:MM:dd HH:mm:ss"))
val dateStr = dateTime.toString(DateTimeFormat.forPattern("yyyy:MM:dd"))
val timeUTCStr = dateTime.withZone(DateTimeZone.UTC).toString(DateTimeFormat.forPattern("HH:mm:ss"))
val offsetStr = dateTime.toString(DateTimeFormat.forPattern("ZZ"))
exif.setAttribute(TAG_DATETIME, dateTimeStr)
exif.setAttribute(TAG_DATETIME_DIGITIZED, dateTimeStr)
exif.setAttribute(TAG_DATETIME_ORIGINAL, dateTimeStr)
exif.setAttribute(TAG_GPS_DATESTAMP, dateStr)
exif.setAttribute(TAG_GPS_TIMESTAMP, timeUTCStr)
exif.setAttribute(TAG_OFFSET_TIME, offsetStr)
exif.setAttribute(TAG_OFFSET_TIME_DIGITIZED, offsetStr)
exif.setAttribute(TAG_OFFSET_TIME_ORIGINAL, offsetStr)
exif.saveAttributes()

-1

我遇到了一个问题,Nexus 6和Lumia 935的图像没有CreateDateDateTimeOriginal字段。

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"

我希望它能帮助到某个人


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接