Imagesデータのデータベースによる管理(API≧29)

投稿日:  更新日:

メディアデータはデータベースによって管理されています。

Media Store APIを使ってメディアデータへアクセスしているのであれば、データベースの所在や構成などを意識する必要はありません。

ただ、「より複雑な制御をしたい場合」や「デバックを効率化したい場合」などに、データベースの知識が役立ちます。

今回は「メディアデータのデータベースによる管理」について、まとめます。

この記事は、Imagesデータ編です。

※環境:Android Studio Narwhal | 2025.1.1 Patch 1

スポンサーリンク

データベースの所在

メディアデータのメディア情報を、データベースで管理しているのはMedia Providerモジュールです。

ですので、データベースは内部ストレージのMedia Providerモジュール固有の領域にあります。

API 29:Media StoreアプリAPI≧30:Media Providerモジュール
# pwd
/data/data/com.android.providers.media    ← Media Storeアプリ固有の領域
# ls -l databases/*
-rw-rw---- 1 u0_a60 u0_a60 155648 2025-06-11 13:12 databases/external.db
-rw-rw---- 1 u0_a60 u0_a60 253952 2025-06-11 13:12 databases/internal.db

※「/data/data」は管理者ユーザー(ユーザーID:0)の内部ストレージと同じ場所
# pwd
/data/data/com.google.android.providers.media.module    ← Media Providerモジュール固有の領域
# ls -l databases/*
-rw-rw---- 1 u0_a166 u0_a166 118784 2025-06-12 01:37 databases/external.db
-rw------- 1 u0_a166 u0_a166  32768 2025-06-12 01:57 databases/external.db-shm
-rw------- 1 u0_a166 u0_a166 453232 2025-06-12 01:56 databases/external.db-wal
-rw-rw---- 1 u0_a166 u0_a166 233472 2025-06-12 01:38 databases/internal.db
-rw------- 1 u0_a166 u0_a166  32768 2025-06-12 01:38 databases/internal.db-shm
-rw------- 1 u0_a166 u0_a166 494432 2025-06-12 01:38 databases/internal.db-wal

※「/data/data」は管理者ユーザー(ユーザーID:0)の内部ストレージと同じ場所
スポンサーリンク

テーブルの構成

データベースは複数のテーブルで構成されています。

API 29API≧30
# pwd
/data/data/com.android.providers.media/databases
# sqlite3 ./external.db
sqlite> .tables
album_art              audio_genres           images
album_info             audio_genres_map       log
albums                 audio_genres_map_noid  search
android_metadata       audio_meta             searchhelpertitle
artist_info            audio_playlists        thumbnails
artists                audio_playlists_map    video
artists_albums_map     downloads              videothumbnails
audio                  files
# pwd
/data/data/com.google.android.providers.media.module/databases
# sqlite3 ./external.db
sqlite> .tables
album_art            audio_playlists      log
android_metadata     audio_playlists_map  search
audio                downloads            searchhelpertitle
audio_albums         files                thumbnails
audio_artists        images               video
audio_genres         local_metadata       videothumbnails

メディア情報の実態は、filesテーブルが持ちます。

imagesテーブルはfilesテーブルからimageメディア情報を切り出したview(仮想テーブル)です。

MediaStoreのデータベースのテーブル

viewテーブルの条件に、media_typeカラム(media_type=1)が用いられています。

API 29API≧30
...
db.execSQL("CREATE TABLE files (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
        + "_data TEXT UNIQUE COLLATE NOCASE,_size INTEGER,format INTEGER,parent INTEGER,"
        + "date_added INTEGER,date_modified INTEGER,mime_type TEXT,title TEXT,"
        + "description TEXT,_display_name TEXT,picasa_id TEXT,orientation INTEGER,"
        + "latitude DOUBLE,longitude DOUBLE,datetaken INTEGER,mini_thumb_magic INTEGER,"
        + "bucket_id TEXT,bucket_display_name TEXT,isprivate INTEGER,title_key TEXT,"
        + "artist_id INTEGER,album_id INTEGER,composer TEXT,track INTEGER,"
        + "year INTEGER CHECK(year!=0),is_ringtone INTEGER,is_music INTEGER,"
        + "is_alarm INTEGER,is_notification INTEGER,is_podcast INTEGER,album_artist TEXT,"
        + "duration INTEGER,bookmark INTEGER,artist TEXT,album TEXT,resolution TEXT,"
        + "tags TEXT,category TEXT,language TEXT,mini_thumb_data TEXT,name TEXT,"
        + "media_type INTEGER,old_id INTEGER,is_drm INTEGER,"
        + "width INTEGER, height INTEGER, title_resource_uri TEXT,"
        + "owner_package_name TEXT DEFAULT NULL,"
        + "color_standard INTEGER, color_transfer INTEGER, color_range INTEGER,"
        + "_hash BLOB DEFAULT NULL, is_pending INTEGER DEFAULT 0,"
        + "is_download INTEGER DEFAULT 0, download_uri TEXT DEFAULT NULL,"
        + "referer_uri TEXT DEFAULT NULL, is_audiobook INTEGER DEFAULT 0,"
        + "date_expires INTEGER DEFAULT NULL,is_trashed INTEGER DEFAULT 0,"
        + "group_id INTEGER DEFAULT NULL,primary_directory TEXT DEFAULT NULL,"
        + "secondary_directory TEXT DEFAULT NULL,document_id TEXT DEFAULT NULL,"
        + "instance_id TEXT DEFAULT NULL,original_document_id TEXT DEFAULT NULL,"
        + "relative_path TEXT DEFAULT NULL,volume_name TEXT DEFAULT NULL)");
...
db.execSQL("CREATE VIEW images AS SELECT "
     + String.join(",", getProjectionMap(Images.Media.class).keySet())
     + " FROM files WHERE media_type=1");
...
...
db.execSQL("CREATE TABLE files (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
        + "_data TEXT UNIQUE COLLATE NOCASE,_size INTEGER,format INTEGER,parent INTEGER,"
        + "date_added INTEGER,date_modified INTEGER,mime_type TEXT,title TEXT,"
        + "description TEXT,_display_name TEXT,picasa_id TEXT,orientation INTEGER,"
        + "latitude DOUBLE,longitude DOUBLE,datetaken INTEGER,mini_thumb_magic INTEGER,"
        + "bucket_id TEXT,bucket_display_name TEXT,isprivate INTEGER,title_key TEXT,"
        + "artist_id INTEGER,album_id INTEGER,composer TEXT,track INTEGER,"
        + "year INTEGER CHECK(year!=0),is_ringtone INTEGER,is_music INTEGER,"
        + "is_alarm INTEGER,is_notification INTEGER,is_podcast INTEGER,album_artist TEXT,"
        + "duration INTEGER,bookmark INTEGER,artist TEXT,album TEXT,resolution TEXT,"
        + "tags TEXT,category TEXT,language TEXT,mini_thumb_data TEXT,name TEXT,"
        + "media_type INTEGER,old_id INTEGER,is_drm INTEGER,"
        + "width INTEGER, height INTEGER, title_resource_uri TEXT,"
        + "owner_package_name TEXT DEFAULT NULL,"
        + "color_standard INTEGER, color_transfer INTEGER, color_range INTEGER,"
        + "_hash BLOB DEFAULT NULL, is_pending INTEGER DEFAULT 0,"
        + "is_download INTEGER DEFAULT 0, download_uri TEXT DEFAULT NULL,"
        + "referer_uri TEXT DEFAULT NULL, is_audiobook INTEGER DEFAULT 0,"
        + "date_expires INTEGER DEFAULT NULL,is_trashed INTEGER DEFAULT 0,"
        + "group_id INTEGER DEFAULT NULL,primary_directory TEXT DEFAULT NULL,"
        + "secondary_directory TEXT DEFAULT NULL,document_id TEXT DEFAULT NULL,"
        + "instance_id TEXT DEFAULT NULL,original_document_id TEXT DEFAULT NULL,"
        + "relative_path TEXT DEFAULT NULL,volume_name TEXT DEFAULT NULL,"
        + "artist_key TEXT DEFAULT NULL,album_key TEXT DEFAULT NULL,"
        + "genre TEXT DEFAULT NULL,genre_key TEXT DEFAULT NULL,genre_id INTEGER,"
        + "author TEXT DEFAULT NULL, bitrate INTEGER DEFAULT NULL,"
        + "capture_framerate REAL DEFAULT NULL, cd_track_number TEXT DEFAULT NULL,"
        + "compilation INTEGER DEFAULT NULL, disc_number TEXT DEFAULT NULL,"
        + "is_favorite INTEGER DEFAULT 0, num_tracks INTEGER DEFAULT NULL,"
        + "writer TEXT DEFAULT NULL, exposure_time TEXT DEFAULT NULL,"
        + "f_number TEXT DEFAULT NULL, iso INTEGER DEFAULT NULL,"
        + "scene_capture_type INTEGER DEFAULT NULL, generation_added INTEGER DEFAULT 0,"
        + "generation_modified INTEGER DEFAULT 0, xmp BLOB DEFAULT NULL)");
...
db.execSQL("CREATE VIEW images AS SELECT "
        + String.join(",", getProjectionMap(Images.Media.class).keySet())
        + " FROM files WHERE media_type=1");
...
スポンサーリンク

カラムの構成

テーブルおよびコレクションは次のカラムを持ちます。

API 29API≧30
データベースの
filesテーブル
データベースの
imagesテーブル
MediaStoreの
imagesコレクション
コメント
_idI_id左に同じPrimary Key
Autoinc
_dataT_dataUnigue
_display_nameT_display_name
_hashB_hash
_sizeI_size
albumT
album_artistT
album_idI
artistT
artist_idI
bookmarkI
bucket_display_nameTbucket_display_name
bucket_idTbucket_id
categoryT
color_rangeI
color_standardI
color_transferI
composerT
date_addedIdate_added
date_expiresIdate_expires
date_modifiedIdate_modified
datetakenIdatetaken
descriptionTdescription
document_idTdocument_id
download_uriT
durationIduration
formatI
group_idIgroup_id
heightIheight
instance_idTinstance_id
is_alarmI0:false
1:true
is_audiobookI
is_downloadI
is_drmIis_drm
is_musicI
is_notificationI
is_pendingIis_pending
is_podcastI
is_ringtoneI
is_trashedIis_trashed
isprivateIisprivate
languageT
latitudeDlatitude
longitudeDlongitude
media_typeI1:Image
2:Audio
3:Video
mime_typeTmime_type
mini_thumb_dataT
mini_thumb_magicImini_thumb_magic
nameT
old_idI
orientationIorientation
original_document_idToriginal_document_id
owner_package_nameTowner_package_name
parentI
picasa_idTpicasa_id
primary_directoryTprimary_directory
referer_uriT
relative_pathTrelative_path
resolutionT
secondary_directoryTsecondary_directory
tagsT
titleTtitle
title_keyT
title_resource_uriT
trackI
volume_nameTvolume_name
widthIwidth
yearI
※カラム名はA-Z順にソート
※I:Integer、R:Real、D:Double、T:Text、B:BLOB(Binary)
※imageコレクション:Media Storeで操作可能なカラム(参照結果のCursorに含まれる)
データベースの
filesテーブル
データベースの
imagesテーブル
MediaStoreの
imagesコレクション
コメント
_idI_id左に同じPrimary Key
Autoinc
_dataT_dataUnigue
_display_nameT_display_name
_hashB
_sizeI_size
albumTalbum
album_artistTalbum_artist
album_idI
album_keyT
artistTartist
artist_idI
artist_keyT
authorTauthor
bitrateIbitrate
bookmarkI
bucket_display_nameTbucket_display_name
bucket_idTbucket_id
capture_framerateRcapture_framerate
categoryT
cd_track_numberTcd_track_number
color_rangeI
color_standardI
color_transferI
compilationIcompilation
composerTcomposer
date_addedIdate_added
date_expiresIdate_expires
date_modifiedIdate_modified
datetakenIdatetaken
descriptionTdescription
disc_numberTdisc_number
document_idTdocument_id
download_uriT
durationIduration
exposure_timeTexposure_time
f_numberTf_number
formatI
generation_addedIgeneration_added
generation_modifiedIgeneration_modified
genreTgenre
genre_idI
genre_keyT
group_idIgroup_id
heightIheight
instance_idTinstance_id
is_alarmI0:false
1:true
is_audiobookI
is_downloadIis_download
is_drmIis_drm
is_favoriteIis_favorite
is_musicI
is_notificationI
is_pendingIis_pending
is_podcastI
is_ringtoneI
is_trashedIis_trashed
isoIiso
isprivateIisprivate
languageT
latitudeDlatitude
longitudeDlongitude
media_typeI1:Images
2:Audio
3:Video
mime_typeTmime_type
mini_thumb_dataT
mini_thumb_magicImini_thumb_magic
nameT
num_tracksInum_tracks
old_idI
orientationIorientation
original_document_idToriginal_document_id
owner_package_nameTowner_package_name
parentI
picasa_idTpicasa_id
primary_directoryT
referer_uriT
relative_pathTrelative_path
resolutionTresolution
scene_capture_typeIscene_capture_type
secondary_directoryT
tagsT
titleTtitle
title_keyT
title_resource_uriT
trackI
volume_nameTvolume_name
widthIwidth
writerTwriter
xmpBxmp
yearIyear
※カラム名はA-Z順にソート
※I:Integer、R:Real、D:Double、T:Text、B:BLOB(Binary)
※imageコレクション:Media Storeで操作可能なカラム(参照結果のCursorに含まれる)

Media Store APIはカラム名をパラメータで定義しています。プログラムは、このパラメータを使います。※詳細は「MediaStore.Images.Media.*」を参照

スポンサーリンク

レコードの構成

レコード(メディア情報)内のフィールドは、次のような関係があります。

  • (1)URIを指定すると、_idが定まる
  • (2)_idを指定すると、メディア情報が一意に定まる
  • (3)メディア情報のrelative_path,_display_nameを指定すると_dataが生成される
  • (4)作成された_dataにより、メディアファイルが一意に定まる

(3,4)のrelative_path, _display_nameおよび_dataとファイルの物理的な関係は「固定」です。

関係が崩れると、Media Storeは破綻します。つまり、データを読み出したり、更新したり、といった正常なアクセスが出来なくなります。

関係が崩れないように、relative_path, _display_nameの変更はファイルへ直ちに反映されます。また、この両者から生成される_dataは、変更が禁止されています。

例えば、表示名を連番から具体的な名前(_display_name:「IMG0011.jpg」→「100万ドルの夜景.jpg」)に変更すると、ファイル名も自動的に変更されます。

レコードの構成

これに対し、relative_path, _display_nameおよび_data以外とファイルの物理的な関係は「なし」です。

これらのフィールドはメディアファイルのメタ情報であって、関係が崩れたとしても、Media Storeは破綻しません。ただし、論理的な関係は維持しないと、メタ情報の意味がありません。

例えば、MIMEタイプを”image/jpeg”⇒”image/png”にすると、読み出しは問題ありませんが、PNGフォーマットと信じたアプリは表示に失敗します。

スポンサーリンク

関連記事:

ストレージのリソースは、内部メモリー、外部メモリー、クラウドの3つがあります。 外部メモリーは、主にSDカードです。 このSDカードはAndroid端末の世代が進むにつれて、扱いを変えてきました。 リソースとSDカードを主眼に置いたストレージの変遷について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
Adoptable Storage(API≧23、Android 6.0)が導入されて、SDカードの扱い方をユーザ側で指定できるようになりました。 「Adoptable Storage」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
ストレージはデータの用途別に記憶領域が分けられます。 保存先を守らないと、セキュリティリスクが発生したり、他のアプリと協調した動作が出来なくなったり、します。 ですので、適切な場所へデータを保存しましょう。 今回は「用途別記憶領域とボリューム」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
ストレージへアクセスする方法は、「扱うデータの種類」「アクセス先」「セキュリティの確保」などの要件により、最適なアクセス方法が存在するので、使い分けが必要です。 今回は「アクセスする方法」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「内部ストレージ」にアクセスする方法について、まとめます。 「内部ストレージ」は、セキュリティが高いうえに、端末の内部メモリーに構築されるので、必ず存在します。 使いたい時に安心して使え、もっとも使い勝手のよいストレージと言えます。 アプリのデータを保存したいならば、保存先として真っ先に考えるストレージです。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
外部ストレージへアクセスするアプリは、パーミッション(許可)をユーザーから取得する必要があります。 パーミッションを得たアプリは、許可された権限の範囲内で、ストレージへアクセスが可能です。 これらは、ユーザーデータのプライバシー保護と密接に関係しています。 プライバシー保護をより強固にするために、パーミッションと権限の範囲の仕様は改変されてきました。 今回は、改変の歴史を辿りつつ、「パーミッションと権限の範囲」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_プライマリ」にアクセスする方法について、まとめます。 「外部ストレージ_プライマリ」は、アプリ間で共有するデータを保存するストレージです。 主にカメラ、音楽プレーヤー、動画プレーヤーで扱うデータを保存します。 「外部ストレージ_プライマリ」に保存したデータは、他のアプリに公開することになるので、秘匿性の高いデータの保存に適しません。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_セカンダリ」にアクセスする方法について、まとめます。 「外部ストレージ_セカンダリ」は、デバイス間(または、アプリ間)で共有するデータを保存するストレージです。 デバイスとは、他の携帯端末やパソコンなどを指します。 ストレージがSDカードのような取り外し可能なリソース上に構築されているので、データの共有は取り外したストレージを他のデバイスへ取り付けて行います。 「外部ストレージ_セカンダリ」に保存したデータは、他のデバイスに公開することになるので、秘匿性の高いデータの保存に適しません。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_プライマリ」に保存されるメディアデータは、Media Storeと呼ばれる特別な方法でアクセスします。 他の方法も可能ですが、Media Storeが最も適した方法です。 この「メディアデータへMedia Storeでアクセス」する方法を、まとめます。 この記事は、Imagesデータ編です。また、基本的なアクセス(読み書き)に的を絞って説明しています。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
メディアデータはデータベースによって管理されています。 Media Store APIを使ってメディアデータへアクセスしているのであれば、データベースの所在や構成などを意識する必要はありません。 ただ、「より複雑な制御をしたい場合」や「デバックを効率化したい場合」などに、データベースの知識が役立ちます。 今回は「メディアデータのデータベースによる管理」について、まとめます。 この記事は、Imagesデータ編です。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_プライマリ」に保存されるメディアデータは、Media Storeと呼ばれる特別な方法でアクセスします。 他の方法も可能ですが、Media Storeが最も適した方法です。 この「メディアデータへMedia Storeでアクセス」する方法を、まとめます。 この記事は、Imagesデータ編です。また、基本的なアクセス(読み書き)に的を絞って説明しています。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
スポンサーリンク