前言
Android多媒体相关的数据都存放在/data/data/com.android.providers.media/文件夹里的external.db和internal.db数据库里,二者的区别主要是前者是针对放在SDCard外部存储多媒体,后者主要针对放在手机本地存储里的多媒体资源。Android 6.0里两个数据库里的数据库表和表结构基本一致,这里只分析external中的表结构。
多媒体资源主要分为三大类图片、视频和音频,其中图片和视频都有缩略图资源,它们都是以文件的形式存在于Android系统中的。这些多媒体文件相关的信息会被记录在一个FILES数据库表中,为了能够更方便的查看不同类型的资源,数据库分别为图片视频和音频增加了视图对象。下面来逐个查看每个表和视图的生成DDL,了解每个字段的类型和用途。
文件数据表
数据表的创建DDL如下,可见每个字段都以下划线“_”开头:
CREATE TABLE "files" (
_id INTEGER PRIMARY KEY AUTOINCREMENT, // 文件的id,从1开始逐渐增加
_data TEXT UNIQUE COLLATE NOCASE, // 数据,实际是文件的保存路径
_size INTEGER, // 多媒体文件的大小
format INTEGER, // 多媒体文件类型
parent INTEGER, // 父文件夹的id
date_added INTEGER, // 多媒体文件添加时间
date_modified INTEGER, // 多媒体文件修改时间
mime_type TEXT, // 文件的媒体类型
title TEXT, // 不带扩展名的文件名
description TEXT, // 文件描述
_display_name TEXT, // 带扩展名的文件名
picasa_id TEXT, // ?
orientation INTEGER, // 取自EXIF旋转角度,在图库旋转图片也会改变此值
latitude DOUBLE, // 拍摄位置经纬度
longitude DOUBLE,
datetaken INTEGER, // 取自EXIF照片拍摄时间,若为空则等于文件修改时间,单位毫秒
mini_thumb_magic INTEGER, // 取小缩略图时生成的一个随机数,见 MediaThumbRequest
bucket_id TEXT, // 包含多媒体文件的bucket id 等于 path.toLowerCase.hashCode(),见 MediaProvider.computeBucketValues()
bucket_display_name TEXT, // 直接包含图片的文件夹就是该图片的 bucket,就是文件夹名
isprivate INTEGER,
title_key TEXT,
artist_id INTEGER, // 艺术家id,有一个艺术家表
album_id INTEGER, // 专辑id,有一个专辑表
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,
storage_id INTEGER,
is_drm INTEGER,
width INTEGER, // 宽高信息
height INTEGER);
从FILES表的字段可以看出,它包含了所有的图片、视频和音频文件信息,文件表记录了具体的文件路径和基本信息,其他Images等视图只需要连表查询就可以得到对应数据。
下面是在文件表上创建的索引对象,在查询使用到索引定义的字段时可以加快查询速度。
CREATE INDEX album_id_idx ON files(album_id);
CREATE INDEX artist_id_idx ON files(artist_id);
CREATE INDEX bucket_index on files(bucket_id,media_type,datetaken, _id);
CREATE INDEX bucket_name on files(bucket_id,media_type,bucket_display_name);
CREATE INDEX format_index ON files(format);
CREATE INDEX media_type_index ON files(media_type);
CREATE INDEX parent_index ON files(parent);
CREATE INDEX path_index ON files(_data);
CREATE INDEX sort_index ON files(datetaken ASC, _id ASC);
CREATE INDEX title_idx ON files(title);
CREATE INDEX titlekey_index ON files(title_key);
最后是触发器对象:
CREATE TRIGGER audio_playlists_cleanup DELETE ON files WHEN old.media_type=4 BEGIN DELETE FROM audio_playlists_map WHERE playlist_id = old._id;SELECT _DELETE_FILE(old._data);END;
CREATE TRIGGER files_cleanup DELETE ON files BEGIN SELECT _OBJECT_REMOVED(old._id);END;
图片资源
图片Images是一个视图对象,创建的DDL如下:
CREATE VIEW images AS
SELECT
_id, // 图片id
_data, // 图片路径
_size, // 图片大小
_display_name, // 待扩展名的文件名
mime_type, // 多媒体类型
title, // 不带扩展名的文件类型
date_added, // 图片添加时间
date_modified, // 图片修改时间
description, // 图片描述
picasa_id,
isprivate,
latitude, // EXIF里的经纬度
longitude,
datetaken, // EXIF里的日期
orientation, // EXIF里的方向
mini_thumb_magic, //
bucket_id, // 图片集id
bucket_display_name, // 图片集名称
width, // 图片宽高信息
height
FROM files // 从文件表中查找media_type为1的记录就是图片多媒体资源
WHERE media_type=1;
可见Image视图所有的字段都取自files表,和图片相关的表还有一个ImageThumbnail图片缩略图表,它的DDL如下:
CREATE TABLE thumbnails (
_id INTEGER PRIMARY KEY, // 缩略图id,从0开始组件增大
_data TEXT, // 缩略图路径
image_id INTEGER, // 缩略图对应的图片id
kind INTEGER, // 缩略图类型缩略图类型,1 是大缩略图,2 基本不用,3 是微型缩略图但其信息不保存在数据库
width INTEGER, // 缩略图宽高
height INTEGER);
CREATE INDEX image_id_index on thumbnails(image_id);
因为大部分情况下是根据图片id查询对应的缩略图资源,在image_id上创建了索引对象加速查找。
视频资源
CREATE VIEW video AS
SELECT
_id, // 视频的id
_data, // 视频的路径
_display_name, // 不带扩展名的文件名
_size, // 视频大小
mime_type,
date_added,
date_modified,
title,
duration,
artist,
album,
resolution, // 解析度
description,
isprivate,
tags,
category,
language,
mini_thumb_data,
latitude,
longitude,
datetaken,
mini_thumb_magic,
bucket_id,
bucket_display_name,
bookmark,
width,
height
FROM files
WHERE media_type=3;
视频所有的字段都从files表里取,只不过视频的media_type是3。除了视频的视图之外还有一个视频缩略图表:
CREATE TABLE videothumbnails (
_id INTEGER PRIMARY KEY, // 缩略图id
_data TEXT, // 缩略图路径
video_id INTEGER, // 缩略图对应的视频
kind INTEGER, // 缩略图类型
width INTEGER, // 缩略图宽高
height INTEGER);
CREATE INDEX video_id_index on videothumbnails(video_id);
视频缩略图表和图片缩略图表基本上一致不再赘述。
音频资源
音频audio_meta视图的DDL对应如下:
CREATE VIEW audio_meta AS
SELECT
_id, // 音频id
_data, // 音频文件路径
_display_name, // 音频文件名不带扩展名
_size, // 音频文件大小
mime_type,
date_added,
is_drm,
date_modified,
title,
title_key,
duration,
artist_id,
composer,
album_id,
track,
year,
is_ringtone,
is_music,
is_alarm,
is_notification,
is_podcast,
bookmark,
album_artist
FROM files
WHERE media_type=2;
所有media_type为2的文件表记录就是音频文件。
再看艺术家和专辑两个表:
CREATE TABLE artists (
artist_id INTEGER PRIMARY KEY, // 艺术家id
artist_key TEXT NOT NULL UNIQUE, // 全大写字母,用于字母索引
artist TEXT NOT NULL // 艺术家名称
);
CREATE INDEX artistkey_index on artists(artist_key);
CREATE INDEX artist_idx on artists(artist);
CREATE TABLE albums (
album_id INTEGER PRIMARY KEY, // 专辑id
album_key TEXT NOT NULL UNIQUE, // 全大写字母,用于字母索引
album TEXT NOT NULL // 专辑名称
);
CREATE TRIGGER albumart_cleanup1 DELETE ON albums BEGIN DELETE FROM album_art WHERE album_id = old.album_id;END;
CREATE INDEX albumkey_index on albums(album_key);
CREATE INDEX album_idx on albums(album);
音频视图需要file表、artist表和album表联合查询,这样艺术家和专辑信息都会被包含在内。
CREATE VIEW audio as
SELECT *
FROM audio_meta
LEFT OUTER JOIN artists
ON audio_meta.artist_id=artists.artist_id
LEFT OUTER JOIN albums
ON audio_meta.album_id=albums.album_id;