スマホを買い替えてAndroid11になった。すると、Android6の時に自作した画像閲覧アプリで、画像をうまく表示できないことがわかった。そのアプリでは、スマホの中の画像を日付順にソートするのに、ContentResolverで、MediaStore.MediaColumns.DATE_TAKENを指定してソートしていた。つまり、
String sortOrder = MediaStore.MediaColumns.DATE_TAKEN;
という感じである。
調べてみると、いつの頃からかDATE_TAKENはAPI level29から追加されたことになり、古いAndroidでは使えなくなったらしい。歴史改変というやつですね。
ただ、悪いことばかりではなく、以前のDATE_TAKENは撮影日付という名称にも関わらず、ファイルの更新日付で決まっていたものが、Exifを読むように変わったらしい。しかし、Exifから決められないものはNULLになっており、一筋縄ではいかない。更に、やっかいなことに、DATE_TAKENはmillisecondsなのに、代わりに使えそうなDATE_MODIFIEDやDATE_ADDEDは秒単位だという。
諦めてDATE_MODIFIEDでソートするという手もあるが、SQLのCASE句を使えば、これを解決できる。こんな感じである。
String sortOrder = {
"CASE WHEN " + MediaStore.Images.ImageColumns.DATE_TAKEN + " is NULL" +
" THEN " + MediaStore.Images.ImageColumns.DATE_MODIFIED + " * 1000" +
" ELSE " + MediaStore.Images.ImageColumns.DATE_TAKEN + " END"};
この勢いでカラムの方もCASE句を使えば状況に応じて日時を取得できるので便利なのだが、残念ながら、最近のContentResolverはカラム指定には単純なカラム名しか受け付けないので、こちらはうまくいかない。
ただ、どうもExifのデータがあっても日付順に並んでくれない画像があることがわかった。リファレンスをよく読んでみると、
信頼のおける決定のためには、ExifInterface#TAG_DATETIME_ORIGINAL と ExifInterface#TAG_OFFSET_TIME_ORIGINAL が定義されていなくてはならない
ということらしく。2つ揃っていないとダメらしい。もう一つ、DATE_TAKENの値はnon-negativeのはずなのだが、実際にContentResolverで取得してみると、-1となっている画像があって、これは謎である。ご存じの方は教えてほしい。
ちなみに、CursorのgetLongのリファレンスをみると、以下のようになっていて、結局よくわからない。
カラムの値がnullもしくはカラムタイプが整数型でない、もしくは整数値がLong型の範囲外の場合の結果および例外を投げるかどうかは実装で定義される。