MediaStore.Images.Media.DATE_TAKEN
カラムと、MediaStore.Images.Media.DATE_ADDED
カラムのタイムスタンプについて勘違いしていたので、まとめておきたいと思います。
「DATE_TAKEN」はミリ秒、「DATE_ADDED」は秒
UNIXエポック(1970年1月1日午前0時0分0秒(UTC))
を基準に、DATE_TAKEN
は経過日数をミリ秒で、DATE_ADDED
は秒で表したタイムスタンプを持っています。
DATE_TAKEN
とDATE_ADDED
のタイムスタンプは、以下のようになっています
DATE_TAKEN
- 1111295661000
DATE_ADDED
- 1602652291
DATE_TAKEN
は、Android 10(Android Q/API Level 29)
から追加されたカラムなので、使用するときは以下のような判定が必要です。
val column = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.DATE_TAKEN
} else {
MediaStore.Images.Media.DATE_ADDED
}
タイムスタンプに関する単語について
よく理解していない単語もあったので、まとめておきたいと思います。
UTC
- Coordinated Universal Timeの略
- 協定世界時のこと
- 世界標準で使われている時間
- 日本(JST/日本標準時)との時差は「9時間」で、UTCが「09:00」なら日本は「18:00」になる
UNIXタイムスタンプ
- 1970年1月1日午前0時0分0秒を基準にして、経過日数を秒で表したもの
UNIXエポック
- 1970年1月1日午前0時0分0秒のこと
日時を指定して端末に保存されている写真を取得する
特定の日時以降に撮影された写真のURIを取得する実装です。日時の取り扱いにはThreeTenABP
ライブラリを使用しています。
app/build.gradle
implementation 'com.jakewharton.threetenabp:threetenabp:1.3.0'
fun loadTakenPhotoUris(context: Context, dateTime: LocalDateTime): List<Uri> {
val uris = mutableListOf<Uri>()
// 取得したいカラムを指定する
val projection: Array<String> = arrayOf(MediaStore.Images.Media._ID)
// 検索条件:特定の日時以降に保存された画像を取得する
val selection = "${MediaStore.Images.Media.DATE_ADDED} >= ?"
val timestamp = toTimestamp(dateTime).toString()
// selectionの「?」に入る値
val selectionArgs: Array<String> = arrayOf(timestamp)
// DATE_ADDEDで昇順にする
val sortOrder = "${MediaStore.Images.Media.DATE_ADDED} ASC"
context.contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
selectionArgs,
sortOrder
).use { cursor ->
cursor ?: return@use
val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
while (cursor.moveToNext()) {
val imageId = cursor.getLong(columnIndex)
val uri = Uri.withAppendedPath(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
imageId.toString()
)
uris.add(uri)
}
}
return uris
}
private fun toTimestamp(dateTime: LocalDateTime): Long {
// JSTに変換
val zonedDateTime = dateTime.atZone(ZoneId.of("UTC+09:00"))
return zonedDateTime.toEpochSecond()
}