Android获取图片拍照时间
as2020200
8年前
<p>为什么写这篇文章是因为今早有个需求需要获取图片拍照时的时间进行一些处理,有些方法参数名忘记了,所以谷歌百度了一下,<code>Android 图片 时间</code>,<code>Android 图片 拍照 时间</code>,这几个关键字居然无法搜索到,那么就在这里留一个印记给需要的人吧。</p> <h2>前言</h2> <p>做过相册的小伙伴应该知道有一个功能是根据照片的拍照时间去排序照片,可以直接从ContentProvider中获取到图片的一些信息,那么直接给你一张图片,你要如何获取图片的信息呢?这就要用到ExifInterface类了。看名字也知道这个类应该分成两段,即"Exif","Interface",也就是说这个类应该是Android对Exif的实现,那么Exif是什么呢?</p> <h2>Exif简介</h2> <p>Exif是一种图像文件格式,它的数据存储与<a href="/misc/goto?guid=4959674883315993197">JPEG</a>格式是完全相同的。实际上Exif格式就是在JPEG格式头部插入了数码照片的信息,包括拍摄时的<a href="/misc/goto?guid=4959674883405314782">光圈</a>、<a href="/misc/goto?guid=4959674883490052227">快门</a>、<a href="/misc/goto?guid=4959674883574013374">白平衡</a>、<a href="/misc/goto?guid=4959674883656713156">ISO</a>、<a href="/misc/goto?guid=4959674883739704461">焦距</a>、日期时间等各种和拍摄条件以及相机品牌、型号、色彩编码、拍摄时录制的声音以及GPS<a href="/misc/goto?guid=4959674883823893839">全球定位系统</a>数据、<a href="/misc/goto?guid=4959674883907890191">缩略图</a>等。你可以利用任何可以查看JPEG文件的看图软件浏览Exif格式的照片,但并不是所有的图形程序都能处理Exif信息。</p> <p>ps:以上简介来着百科</p> <h2>ExifInterface简介</h2> <p>ExifInterface是Android下一个操作Exif信息的实现类,是媒体库的功能实现类。</p> <p>构造函数</p> <pre> <code class="language-java">/** * Reads Exif tags from the specified JPEG file. */ public ExifInterface(String filename) throws IOException { if (filename == null) { throw new IllegalArgumentException("filename cannot be null"); } mFilename = filename; loadAttributes(); }</code></pre> <p>构造函数接收一个字符串形式的图片地址:<br> <code>/storage/emulated/0/DCIM/P60626-135914.jpg</code></p> <p>使用方法</p> <p>初始化后,系统会把解析好的图片Exif信息使用键值对的方式存储在<code>private HashMap<String, String> mAttributes;</code>中,这时我们使用<code>getAttribute(String tag)</code>方法就可以获取到相应的值了。</p> <p>其中主要方法有:</p> <pre> <code class="language-java">/** * Returns the value of the specified tag or {@code null} if there * is no such tag in the JPEG file. * * @param tag the name of the tag. */ public String getAttribute(String tag) { return mAttributes.get(tag); } public double getAttributeDouble(String tag, double defaultValue) { ... } public double getAttributeInt(String tag, double defaultValue) { ... } /** * Set the value of the specified tag. * * @param tag the name of the tag. * @param value the value of the tag. */ public void setAttribute(String tag, String value) { mAttributes.put(tag, value); } public void saveAttributes() throws IOException { ... }</code></pre> <p><code>getAttributeDouble()</code>和<code>getAttributeDouble()</code>的实现只是调用<code>getAttribute()</code>后进行一些转换而已。</p> <p>这里我们主要看一下<code>saveAttributes()</code>方法的源码:</p> <pre> <code class="language-java">public void saveAttributes() throws IOException { // format of string passed to native C code: // "attrCnt attr1=valueLen value1attr2=value2Len value2..." // example: // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO" StringBuilder sb = new StringBuilder(); int size = mAttributes.size(); if (mAttributes.containsKey("hasThumbnail")) { --size; } sb.append(size + " "); for (Map.Entry<String, String> iter : mAttributes.entrySet()) { String key = iter.getKey(); if (key.equals("hasThumbnail")) { // this is a fake attribute not saved as an exif tag continue; } String val = iter.getValue(); sb.append(key + "="); sb.append(val.length() + " "); sb.append(val); } String s = sb.toString(); synchronized (sLock) { saveAttributesNative(mFilename, s); commitChangesNative(mFilename); } }</code></pre> <p>可以看出,先是<code>entrySet</code>遍历了所以的属性值,确实是使用的键值对的方式进行存储Exif信息的。</p> <p>常用的Exif支持的tag有:</p> <blockquote> <p>TAG_APERTURE:光圈值<br> TAG_DATETIME:拍摄时间(取决于设备设置的时间)<br> TAG_EXPOSURE_TIME:曝光时间<br> TAG_FLASH:闪光灯<br> TAG_FOCAL_LENGTH:焦距<br> TAG_IMAGE_LENGTH:图片高度<br> TAG_IMAGE_WIDTH:图片宽度<br> TAG_ISO:ISO<br> TAG_MAKE:设备<br> TAG_MODEL:设备型号<br> TAG_ORIENTATION:旋转角度</p> </blockquote> <p>ps:全部tag查看ExifInterface的源码吧,还挺多的。</p> <p>简单的Demo演示</p> <pre> <code class="language-java"> mImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { String path = (String) v.getTag(); Log.i(TAG, "path:" + path); ExifInterface exifInterface = new ExifInterface(path); String TAG_APERTURE = exifInterface.getAttribute(ExifInterface.TAG_APERTURE); String TAG_DATETIME = exifInterface.getAttribute(ExifInterface.TAG_DATETIME); String TAG_EXPOSURE_TIME = exifInterface.getAttribute(ExifInterface.TAG_EXPOSURE_TIME); String TAG_FLASH = exifInterface.getAttribute(ExifInterface.TAG_FLASH); String TAG_FOCAL_LENGTH = exifInterface.getAttribute(ExifInterface.TAG_FOCAL_LENGTH); String TAG_IMAGE_LENGTH = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_LENGTH); String TAG_IMAGE_WIDTH = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_WIDTH); String TAG_ISO = exifInterface.getAttribute(ExifInterface.TAG_ISO); String TAG_MAKE = exifInterface.getAttribute(ExifInterface.TAG_MAKE); String TAG_MODEL = exifInterface.getAttribute(ExifInterface.TAG_MODEL); String TAG_ORIENTATION = exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION); String TAG_WHITE_BALANCE = exifInterface.getAttribute(ExifInterface.TAG_WHITE_BALANCE); Log.i(TAG, "光圈值:" + TAG_APERTURE); Log.i(TAG, "拍摄时间:" + TAG_DATETIME); Log.i(TAG, "曝光时间:" + TAG_EXPOSURE_TIME); Log.i(TAG, "闪光灯:" + TAG_FLASH); Log.i(TAG, "焦距:" + TAG_FOCAL_LENGTH); Log.i(TAG, "图片高度:" + TAG_IMAGE_LENGTH); Log.i(TAG, "图片宽度:" + TAG_IMAGE_WIDTH); Log.i(TAG, "ISO:" + TAG_ISO); Log.i(TAG, "设备品牌:" + TAG_MAKE); Log.i(TAG, "设备型号:" + TAG_MODEL); Log.i(TAG, "旋转角度:" + TAG_ORIENTATION); Log.i(TAG, "白平衡:" + TAG_WHITE_BALANCE); /* Date date = UtilsTime.stringTimeToDate(TAG_DATETIME, new SimpleDateFormat("yyyy:MM:dd HH:mm:ss", Locale.getDefault())); String FStringTime = UtilsTime.dateToStringTime(date, new SimpleDateFormat("yyyy年MM月dd日", Locale.getDefault())); mTextView.setText("TAG_DATETIME = " + TAG_DATETIME + "\n" + "FStringTime = " + FStringTime); */ } catch (Exception e) { e.printStackTrace(); } } }); }</code></pre> <p><img alt="Android获取图片拍照时间" src="https://simg.open-open.com/show/64b82e0e495c0b647aadcb44a4d03580.png"></p> <p>Log</p> <p>Whitelaning<br> It's very easy to be different but very difficult to be better</p> <p><br> </p> <p>来自:文/<a href="/misc/goto?guid=4959674883989093267">白一辰</a>(简书)<br> </p>