MediaStore 是 Android 系统提供的提供器(ContentProvider),用于统一管理设备中的媒体文件(图片、视频、音频、下载项等),它通过标准化的接口实现对媒体数据的增删改查,并维护媒体库的索引(如缩略图生成、文件路径映射等)。
子节点 | 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 类型) |
字段名 | 类型 | 描述 |
---|---|---|
_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 | 文件绝对路径(需权限读取) |
// 获取 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);
MediaStore
或 Storage Access Framework
。MediaStore.insert()
替代直接文件写入。ACTION_OPEN_DOCUMENT
获取文件 URI。READ_EXTERNAL_STORAGE
或 MANAGE_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);
解答:
在 Android 11 中,直接通过文件路径写入公共目录会被限制,需使用 MediaStore
API:
ContentResolver.insert()
将文件信息插入 MediaStore
。// 示例代码(需处理权限) 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);
解答:
通过 ContentObserver
监听 MediaStore
的 DELETE
操作:
ContentObserver
到目标 URI
(如 MediaStore.Images.Media.EXTERNAL_CONTENT_URI
)。onChange()
中判断操作类型(需结合其他逻辑确认是删除)。