ギャラリーアプリが、画像をアルバム(フォルダ)ごとにわけているのを見て、データベース上にアルバムを識別する ID があるのだなと思って調べてみた。
MediaStore が持つアルバムの識別子
アルバムの識別子は BUCKET_ID というのがデータベースのカラムに存在していて、そこに保存されている。
BUCKET_ID と BUCKET_DISPLAY_NAME だけを管理するような、リレーショナルな構造にはなっておらず、画像データに関するカラムとアルバムに関するカラムがくっついた状態になっている。
アルバムごとに GROUP BY する
ギャラリーのように、アルバムごとにリストをつくろうと思うと、SQL でアルバムごとに GROUP BY した結果が欲しくなる。しかし、ContentResolver で問い合わせる時に、GROUP BY をするようなインタフェースは存在しないので、無理やり SQL をねじ込むことになる。
コードはこのヘルパにあるとおりで、WHERE 句が内部的にWHERE (%s)
と書かれていて、SELECTION がこの %s に入ることを利用して、SQL インジェクションもびっくりの 1) GROUP BY 1, (2
を入れることで、WHERE (1) GROUP BY 1,(2)
なる SQL 文が完成する。SELECT 文では、BUCKET_ID が最初のカラムに指定されているので、これによってグルーピングされる。
ところで、画像を MediaStore に登録するときに BUCKET_ID なんか自分で指定したこと無いんだけど
公式の API にも、BUCKET_ID を自分で指定するようなものは無い。
無いということは、どこかで自動で計算しているはず、ということで探してみた。
MediaStore が見に行くのは、MediaProvider という ContentProvider。その中で、computeBucketValues なるメソッドがあって、ここで BUCKET_ID が計算されている。
コード上はこのあたりにある。
画像を保存したディレクトリのパス文字列を全て小文字にした上で、その hashCode() を BUCKET_ID にしています。
そういうわけで
GROUP BY の闇はアプリの中においておきたくないので、ライブラリにまとめてみました。
BucketId の闇も何とか出来る部分は何とかしたい。