Android 获取图片、音视频拍摄时间

一. 使用框架 FileOperator

FileUtils.kt#L37 👉 github.com/javakam/Fil…

二. 复制所需代码

1.使用

image.png

2.API

/**
 * 获取媒体文件的"拍摄时间" (Get the "shooting time" of the media file)
 *
 * 【注】获取拍摄时间优先级: 图片(ExifInterface) ; 视频,音频(MediaMetadataRetriever) ; 最后如果前两者都没获取到时间, 则使用文件最后修改时间(lastModified)
 *
 * 【Note】Get the shooting time priority: Picture (ExifInterface); Video, Audio (MediaMetadataRetriever); Finally, if the first two do not get the time, use the last modified time of the file (lastModified
 */
fun getMediaShotTime(uri: Uri?, block: (Long) -> Unit) {
    if (uri == null) return block.invoke(-1)
    //直接使用 File(mediaFile.path) 获取不到信息 (No information can be obtained directly using File(mediaFile.path))
    //eg: /storage/emulated/0/Movies/VID_20210621_17180117.mp4 true false 1624267109000 ; isFile=false  isDirectory=false  lastModified=0
    val fileReal = File(getPathByUri(uri) ?: return block.invoke(-1))
    //如果 ExifInterface 或 MediaMetadataRetriever 没有获取到时间,使用 lastModified 时间
    //If ExifInterface or MediaMetadataRetriever does not get the time, use the lastModified time
    var fileLastModifiedTime: Long = fileReal.lastModified()
    fileLastModifiedTime = if (fileLastModifiedTime > 0) fileLastModifiedTime else System.currentTimeMillis()
    FileLogger.d(
        "isFile=${fileReal.isFile}  isDirectory=${fileReal.isDirectory}  lastModified=$fileLastModifiedTime"
    )
    //注意:先用 ExifInterface , 后用 MediaMetadataRetriever (Note: Use ExifInterface first, then MediaMetadataRetriever)
    //如果给把图片的 Uri 交给 MediaMetadataRetriever 处理会报错: setDataSource failed: status = 0x80000000
    //If the Uri of the picture is handed over to MediaMetadataRetriever for processing, an error will be reported: setDataSource failed: status = 0x80000000
    try {
        FileOperator.getContext().contentResolver.openInputStream(uri)?.use { i: InputStream ->
            val exifInterface = ExifInterface(i)
            val dateTime: String? = exifInterface.getAttribute(ExifInterface.TAG_DATETIME)
            val modifiedTime: Long
            // 图片(Image)
            // longitude = 0/1,0/1,0/1
            // latitude=0/1,0/1,0/1
            // device_type=NEX 3 5G
            // dateTime=2021:07:12 14:36:30
            // dateTimeOriginal=2021:07:12 14:36:30
            // dateTimeDigitized=2021:07:12 14:36:30
            if (dateTime.isNullOrBlank()) {//1.视频,音频 (Video, audio)
                //ExifInterface 获取到的 ExifInterface.TAG_DATETIME 返回 null, 使用 MediaMetadataRetriever 重新获取
                //ExifInterface.TAG_DATETIME obtained by ExifInterface returns null, use MediaMetadataRetriever to get it again
                val mmr = MediaMetadataRetriever()
                modifiedTime = try {
                    mmr.setDataSource(FileOperator.getContext(), uri)
                    //获取媒体的日期(Date the media was acquired): "20210708T070344.000Z"
                    val dateString = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE)
                    formatMediaMetadataKeyDate(dateString)?.time ?: fileLastModifiedTime
                } catch (e: Exception) {
                    FileLogger.e("getMediaShotTime: ${e.message}")
                    fileLastModifiedTime
                } finally {
                    mmr.release()
                }
            } else {//2.图片(Image)  ExifInterface.TAG_DATETIME  dateTime=2021:07:12 14:36:30
                modifiedTime = SimpleDateFormat("yyyy:MM:dd HH:mm:ss", Locale.getDefault()).parse(dateTime)?.time ?: fileLastModifiedTime
            }
            block.invoke(modifiedTime)
        } ?: block.invoke(fileLastModifiedTime)
    } catch (t: Throwable) {
        FileLogger.e("getMediaShotTime: ${t.message}")
    }
}
/**
 * 转换 MediaMetadataRetriever.METADATA_KEY_DATE 特殊的时间格式:
 *
 * Convert MediaMetadataRetriever.METADATA_KEY_DATE to special time format:
 *
 * eg: "20210708T070344.000Z" 👉 Date()
 *
 * > Thanks
 *
 * https://stackoverflow.com/questions/38648437/android-mediametadataretriever-metadata-key-date-gives-only-date-of-video-on-gal/39828238
 *
 * https://blog.csdn.net/qq_31332467/article/details/79166945
 *
 * @param date "20210708T070344.000Z"
 * @return Date Object
 */
fun formatMediaMetadataKeyDate(date: String?): Date? {
    if (date.isNullOrBlank()) return null
    var inputDate: Date? = null
    try {
        inputDate = SimpleDateFormat("yyyyMMdd'T'HHmmss.SSS Z", Locale.getDefault()).parse(date.replace("Z", " UTC")) ?: return null
    } catch (e: Exception) {
        FileLogger.w("error parsing date: $e")
        try {
            inputDate = SimpleDateFormat("yyyy MM dd.SSS Z", Locale.getDefault()).parse(date.replace("Z", " UTC")) ?: return null
        } catch (ex: Exception) {
            FileLogger.e("error parsing date: $ex")
        }
    }
    FileLogger.i("formatMediaMetadataKeyDate: ${inputDate?.time}")
    return inputDate
}
posted @ 2021-08-17 12:04  javakam  阅读(0)  评论(0)    收藏  举报  来源