「外部ストレージ_プライマリ」に保存されるメディアデータは、データベースで管理されます。
Media Storeを使うと、このデータベースを通してメディアデータへアクセスできます。
データベース(SQLite)が持つ検索機能を使ってアクセス対象を絞り込めるので、とても便利です。
この記事は、「絞り込みアクセス」について、まとめます。
※環境:Android Studio Narwhal | 2025.1.1 Patch 1
目次
絞り込みアクセス
メディアデータへMedia Storeでアクセスする際に、次のコマンドが使われます。
- ContentResolver#query … メディア情報の参照
- ContentResolver#update … メディア情報の更新
- ContentResolver#delete … メディア情報の削除
これらのコマンドは、アクセス対象のメディア情報を絞り込む機能があります。
@Nullable
public final Cursor query(
@NonNull Uri uri,
@Nullable String[] projection, // 取得するカラム
@Nullable String selection, // 検索条件
@Nullable String[] selectionArgs, // 検索条件の値
@Nullable String sortOrder // ソート順
) { ... }
public final int update(
@NonNull Uri uri,
@Nullable ContentValues values,
@Nullable String where, // 検索条件(selectionと同じ)
@Nullable String[] selectionArgs // 検索条件の値
) { ... }
public final int delete(
@NonNull Uri url,
@Nullable String where, // 検索条件(selectionと同じ)
@Nullable String[] selectionArgs // 検索条件の値
) { ... }
そして、絞り込みの条件は引数で指定します。
(1)projection引数は、アクセスするカラムを絞り込み ※queryのみ
(2)selection/selectionArgs引数は、カラム値が条件に合うメディア情報を絞り込み
(1)projection(queryのみ)
projectionへアクセス対象のカラム名をString配列で指定します。
queryにおいて、結果(Cursorオブジェクト)が指定したカラムに限定されます。
# pwd /data/data/com.android.providers.media/databases # sqlite3 ./external.db sqlite> .headers on sqlite> .mode column sqlite> select * from images; _id _data _size _display_name mime_type title date_added date_modified description picasa_id isprivate latitude longitude datetaken orientation mini_thumb_magic bucket_id bucket_display_name width height ---------- ---------------------------------------------- ---------- ----------------- ---------- ------------- ---------- ------------- ----------- ---------- ---------- ---------- ---------- ---------- ----------- ---------------- ----------- ------------------- ---------- ---------- 26 /storage/emulated/0/Pictures/1754872524603.jpg 1754872524603.jpg image/jpeg 1754872524603 1754872524 -1617409521 Pictures 27 /storage/emulated/0/DCIM/1754872524618.jpg 1754872524618.jpg image/jpeg 1754872524618 1754872524 -2075821635 DCIM 28 /storage/emulated/0/Pictures/1754872524622.png 1754872524622.png image/png 1754872524622 1754872524 -1617409521 Pictures 29 /storage/emulated/0/DCIM/1754872524628.png 1754872524628.png image/png 1754872524628 1754872524 -2075821635 DCIM
// val _projection = null // 取得するカラム(※1)
val _projection = arrayOf( // 取得するカラム
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DISPLAY_NAME
)
val _selection = null // 検索条件
val _selectionArgs = null // 検索条件の値
val _sortOrder = null // ソート順
val _cursor = contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
_projection,
_selection,
_selectionArgs,
_sortOrder
)
_cursor?.use { dumpCursor(it) }
Column names = [_id, _display_name] Media id = 26 Media id = 27 Media id = 28 Media id = 29
ちなみに、nullを指定(※1)すると、絞り込みは無効になり、すべてのカラムがアクセス対象になります。
Column names = [_id, _data, _size, _display_name, mime_type, title, date_added, date_modified, description, picasa_id, isprivate, latitude, longitude, datetaken, orientation, mini_thumb_magic, bucket_id, bucket_display_name, width, height] Media id = 26 Media id = 27 Media id = 28 Media id = 29
(2)selection/selectionArgs
カラム値が条件に合うロウ(メディア情報)をアクセス対象にします。SQLの「WHERE句」と同じです。
selectionへ条件式を指定します。この条件式に「?」があると、「?」はselectArgsの値に置き換わります。
selectArgsは条件値をString配列で指定します。
- 左から1番目の「?」 ← selectArgsの[0]
- 左から2番目の「?」 ← selectArgsの[1]
- 左から3番目の「?」 ← selectArgsの[2]
- …
# pwd /data/data/com.android.providers.media/databases # sqlite3 ./external.db sqlite> .headers on sqlite> .mode column sqlite> select _id,_display_name,mime_type from images; _id _display_name mime_type ---------- ----------------- ---------- 26 1754872524603.jpg image/jpeg 27 1754872524618.jpg image/jpeg 28 1754872524622.png image/png 29 1754872524628.png image/png
val _projection = null // 取得するカラム
// val _selection = null // 検索条件(※2)
// val _selectionArgs = null // 検索条件の値
val _selection = "${MediaStore.Images.Media.MIME_TYPE}=?"
val _selectionArgs = arrayOf(
"image/png"
)
val _sortOrder = null // ソート順
val _cursor = contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
_projection,
_selection,
_selectionArgs,
_sortOrder
)
_cursor?.use { dumpCursor(it) }
Column names = [_id, _data, _size, _display_name, mime_type, title, date_added, date_modified, description, picasa_id, isprivate, latitude, longitude, datetaken, orientation, mini_thumb_magic, bucket_id, bucket_display_name, width, height] Media id = 28 ... PNG Media id = 29
ちなみに、nullを指定(※2)すると、絞り込みは無効になり、すべてのロウ(メディア情報)がアクセス対象になります。
Column names = [_id, _data, _size, _display_name, mime_type, title, date_added, date_modified, description, picasa_id, isprivate, latitude, longitude, datetaken, orientation, mini_thumb_magic, bucket_id, bucket_display_name, width, height] Media id = 26 ... JPEG Media id = 27 Media id = 28 ... PNG Media id = 29
例:id(複数)を持つメディア情報
複数のidを指定し、そのidを持つメディア情報へ絞り込む例です。
複数の条件式を「or」で連結することも出来ますが、idの個数が可変なら「in」の利用が得策です。
sqlite> select _id,_display_name,mime_type from images; _id _display_name mime_type ---------- ----------------- ---------- 26 1754872524603.jpg image/jpeg 27 1754872524618.jpg image/jpeg 28 1754872524622.png image/png 29 1754872524628.png image/png 30 1754879401184.jpg image/jpeg 31 1754879401204.jpg image/jpeg 32 1754879401210.png image/png 33 1754879401215.png image/png
val _ids = "'27','29','32'" // id(複数)
val _projection = null // 取得するカラム
val _selection = "${MediaStore.Images.Media._ID} in (${_ids})"
val _selectionArgs = null
val _sortOrder = null // ソート順
val _cursor = contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
_projection,
_selection,
_selectionArgs,
_sortOrder
)
_cursor?.use { dumpCursor(it) }
Column names = [_id, _data, _size, _display_name, mime_type, title, date_added, date_modified, description, picasa_id, isprivate, latitude, longitude, datetaken, orientation, mini_thumb_magic, bucket_id, bucket_display_name, width, height] Media id = 27 Media id = 29 Media id = 32
例:nullを持つメディア情報
SQLiteにおいて、値が未指定のフィールドはnullです。
nullを持つメディア情報へ絞り込む例です。
sqlite> select _id,_display_name,mime_type,isprivate from images; _id _display_name mime_type isprivate ---------- ----------------- ---------- ---------- 26 1754872524603.jpg image/jpeg ... isprivate:null 27 1754872524618.jpg image/jpeg 0 ... ispribate:false 28 1754872524622.png image/png 29 1754872524628.png image/png 30 1754879401184.jpg image/jpeg 0 31 1754879401204.jpg image/jpeg 0 32 1754879401210.png image/png 33 1754879401215.png image/png 0 ※isprivateはBoolean、0:false/1:true(正しくは>0)
val _projection = null // 取得するカラム
val _selection = "${MediaStore.Images.Media.IS_PRIVATE} is null"
val _selectionArgs = null
val _sortOrder = null // ソート順
val _cursor = contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
_projection,
_selection,
_selectionArgs,
_sortOrder
)
_cursor?.use { dumpCursor(it) }
Column names = [_id, _data, _size, _display_name, mime_type, title, date_added, date_modified, description, picasa_id, isprivate, latitude, longitude, datetaken, orientation, mini_thumb_magic, bucket_id, bucket_display_name, width, height] Media id = 26 Media id = 28 Media id = 29 Media id = 32
例:範囲内のメディア情報
昨日追加されたメディア情報へ絞り込む例です。
上限と下限の条件式をandを用いて連結しています。上限の境界を「<」にするためです。
範囲の指定に「between」も利用可能ですが、境界が「下限≦x≦上限」になってしまいます。
sqlite> select _id,_display_name,date_added from images; _id _display_name date_added ---------- ----------------- ---------- 26 1754809710812.jpg 1754809710 ... '25/08/10(Yesterday) 27 1754809710882.jpg 1754809710 28 1754809710888.png 1754809710 29 1754809710892.png 1754809710 30 1754896131558.jpg 1754896131 ... '25/08/11(Today) 31 1754896131565.jpg 1754896131 32 1754896131570.png 1754896131 33 1754896131578.png 1754896131
val _dayBefore = calcDayBefore()
val _start = _dayBefore.first
val _end = _dayBefore.second
val _projection = null // 取得するカラム
val _selection = "${MediaStore.Images.Media.DATE_ADDED}>=? and ${MediaStore.MediaColumns.DATE_ADDED}<?"
val _selectionArgs = arrayOf(
_start.toString(),
_end.toString()
)
val _sortOrder = null // ソート順
val _cursor = contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
_projection,
_selection,
_selectionArgs,
_sortOrder
)
_cursor?.use { dumpCursor(it) }
Column names = [_id, _data, _size, _display_name, mime_type, title, date_added, date_modified, description, picasa_id, isprivate, latitude, longitude, datetaken, orientation, mini_thumb_magic, bucket_id, bucket_display_name, width, height] Media id = 26 Media id = 27 Media id = 28 Media id = 29
Appendix:並び替え(sortOrder、queryのみ)
queryにおいて、sortOrderで結果の並び替えが行えます。SQLの「ORDER BY句」と同じです。
sqlite> select _id,_display_name,date_added from images; _id _display_name date_added ---------- ----------------- ---------- 26 1754899102809.jpg 1754899102 27 1754553524108.jpg 1754553524 28 1754639949043.jpg 1754639949 29 1754380767668.jpg 1754380767 30 1754899187882.jpg 1754899187
val _projection = null // 取得するカラム
val _selection = null // 検索条件
val _selectionArgs = null // 検索条件の値
val _sortOrder = null // ソート順
// val _sortOrder = MediaStore.MediaColumns.DATE_ADDED
// val _sortOrder = "${MediaStore.MediaColumns.DATE_ADDED} ASC"
// val _sortOrder = "${MediaStore.MediaColumns.DATE_ADDED} DESC"
val _cursor = contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
_projection,
_selection,
_selectionArgs,
_sortOrder
)
_cursor?.use { dumpCursor(it) }
null
プライマリーキー(サンプルは_id)をソート対象にして、昇順に並び替えます。
Column names = [_id, _data, _size, _display_name, mime_type, title, date_added, date_modified, description, picasa_id, isprivate, latitude, longitude, datetaken, orientation, mini_thumb_magic, bucket_id, bucket_display_name, width, height] Media id = 26 Media id = 27 Media id = 28 Media id = 29 Media id = 30
カラム指定+ASC(昇順、デフォルト)
指定したカラム値をソート対象にして、昇順に並び替えます。
ASCはデフォルトです。「指定なし」はASCになります。
Column names = [_id, _data, _size, _display_name, mime_type, title, date_added, date_modified, description, picasa_id, isprivate, latitude, longitude, datetaken, orientation, mini_thumb_magic, bucket_id, bucket_display_name, width, height] Media id = 29 Media id = 27 Media id = 28 Media id = 26 Media id = 30
カラム指定+DESC(降順)
指定したカラム値をソート対象にして、降順に並び替えます。
Column names = [_id, _data, _size, _display_name, mime_type, title, date_added, date_modified, description, picasa_id, isprivate, latitude, longitude, datetaken, orientation, mini_thumb_magic, bucket_id, bucket_display_name, width, height] Media id = 30 Media id = 26 Media id = 28 Media id = 27 Media id = 29
関連記事:
