当前位置:首页 > 行业动态 > 正文

安卓媒体数据库

安卓媒体数据库用于存储设备多媒体文件元数据,如图片、音频、视频的路径、名称等信息,常见为MediaStore,供系统和应用快速检索

安卓媒体数据库(MediaStore)详解


MediaStore

MediaStore 是 Android 系统提供的提供器(ContentProvider),用于统一管理设备中的媒体文件(图片、视频、音频、下载项等),它通过标准化的接口实现对媒体数据的增删改查,并维护媒体库的索引(如缩略图生成、文件路径映射等)。

安卓媒体数据库


MediaStore 核心子节点与 URI

子节点 URI 描述
MediaStore.Images content://media/external/images/media 设备内置或外置存储的图片
MediaStore.Video content://media/external/video/media 设备内置或外置存储的视频
MediaStore.Audio content://media/external/audio/media 设备内置或外置存储的音频
MediaStore.Files content://media/external/files 任意文件(需指定 MIME 类型)

MediaStore 常用字段

字段名 类型 描述
_id INTEGER 唯一标识符(主键)
date_added INTEGER 文件添加时间(毫秒级时间戳)
date_modified INTEGER 文件修改时间(毫秒级时间戳)
mime_type TEXT 文件 MIME 类型(如 image/jpeg
display_name TEXT 文件显示名称(含扩展名)
size INTEGER 文件大小(字节)
width / height INTEGER 图片/视频宽度/高度(像素)
duration INTEGER 音频/视频时长(毫秒)
data STRING 文件绝对路径(需权限读取)

MediaStore 操作示例

查询所有图片

// 获取 ContentResolver
ContentResolver resolver = context.getContentResolver();
// 构建查询条件(可选)
String[] projection = {
    MediaStore.Images.Media._ID,
    MediaStore.Images.Media.DATA,
    MediaStore.Images.Media.DATE_ADDED
};
// 执行查询
Cursor cursor = resolver.query(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    projection,
    null, // 无筛选条件
    null, // 无排序参数
    null
);
// 解析结果
if (cursor != null) {
    while (cursor.moveToNext()) {
        long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
        String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
        long dateAdded = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));
        // 处理数据...
    }
    cursor.close();
}

插入新图片到媒体库

// 创建文件并写入数据(假设已获取文件路径)
File file = new File(context.getExternalFilesDir(null), "example.jpg");
// 写入文件逻辑...
// 插入到 MediaStore
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
values.put(MediaStore.Images.Media.DISPLAY_NAME, "example.jpg");
Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

删除媒体文件

// 通过文件路径删除
String filePath = "/storage/emulated/0/DCIM/example.jpg";
String whereClause = MediaStore.Images.Media.DATA + "=?";
String[] args = { filePath };
int deletedRows = resolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, whereClause, args);

Android 10+ 适配(分区存储)

  • 限制:Android 10(Q)及以上版本限制直接访问外部存储,必须通过 MediaStoreStorage Access Framework
  • 适配方案
    1. 使用 MediaStore.insert() 替代直接文件写入。
    2. 通过 ACTION_OPEN_DOCUMENT 获取文件 URI。
    3. 申请 READ_EXTERNAL_STORAGEMANAGE_EXTERNAL_STORAGE 权限(需谨慎)。

监听媒体库变化

通过 ContentObserver 监听媒体库增删改:

// 注册观察者
ContentObserver observer = new ContentObserver(handler) {
    @Override
    public void onChange(boolean selfChange, Uri uri) {
        super.onChange(selfChange, uri);
        // 处理媒体库变化(如重新加载数据)
    }
};
resolver.registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, observer);
// 取消观察
resolver.unregisterContentObserver(observer);

缩略图生成与媒体扫描

  • 自动生成缩略图:插入媒体文件后,系统会自动生成缩略图并更新数据库。
  • 手动触发扫描
    // 发送广播通知系统扫描文件
    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    intent.setDataAndNormalize(Uri.fromFile(file));
    context.sendBroadcast(intent);

相关问题与解答

问题 1:Android 11 如何保存图片到公共图库?

解答
在 Android 11 中,直接通过文件路径写入公共目录会被限制,需使用 MediaStore API:

安卓媒体数据库

  1. 创建文件并写入数据。
  2. 调用 ContentResolver.insert() 将文件信息插入 MediaStore
  3. 系统会自动生成缩略图并更新媒体库。
// 示例代码(需处理权限)
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/Camera"); // 保存到公共目录
values.put(MediaStore.Images.Media.IS_PENDING, 1); // 标记为待处理
Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
// 写入文件后更新状态
values.clear();
values.put(MediaStore.Images.Media.IS_PENDING, 0);
resolver.update(uri, values, null, null);

问题 2:如何监听媒体文件的删除事件?

解答
通过 ContentObserver 监听 MediaStoreDELETE 操作:

安卓媒体数据库

  1. 注册 ContentObserver 到目标 URI(如 MediaStore.Images.Media.EXTERNAL_CONTENT_URI)。
  2. onChange() 中判断操作类型(需结合其他逻辑确认是删除)。
  3. 如果需精确判断删除事件,可结合文件路径或 ID 进行过滤