Android读取本地照片和视频相册实例代码
发布时间 - 2026-01-11 01:44:54 点击率:次前言

项目中经常要选择本地照片或者视频的需求,如果去扫描整个SD卡就太耗时间,其实Android系统在启动时就已经把整个设备中的多媒体文件信息(文件名,类型,大小等)都存到了数据库,然后提供了ContentPrivider这个API来管理这个数据库,我们可以利用ContentPrivider来获取所有的照片和视频。
ContentPrivider初识
先看下管理的的数据库在哪
data/data/目录下:有很多这种文件夹(日历,联系人,下载管理,多媒体等)
我们需要的照片和视频就在media下面,进去看看。进去找到database然后打开external.db,就可以看到多张表(音频,文件,Log,图像,视频等)
照片相册
那么获取照片直接通过 ContentProvider读取Images这个数据库就OK了,这里开启工作线程读取所有.jpeg和.png的图片,附上代码段:
/**
* 读取手机中所有图片信息
*/
private void getAllPhotoInfo() {
new Thread(new Runnable() {
@Override
public void run() {
List<MediaBean> mediaBeen = new ArrayList<>();
HashMap<String,List<MediaBean>> allPhotosTemp = new HashMap<>();//所有照片
Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projImage = { MediaStore.Images.Media._ID
, MediaStore.Images.Media.DATA
,MediaStore.Images.Media.SIZE
,MediaStore.Images.Media.DISPLAY_NAME};
Cursor mCursor = getContentResolver().query(mImageUri,
projImage,
MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?",
new String[]{"image/jpeg", "image/png"},
MediaStore.Images.Media.DATE_MODIFIED+" desc");
if(mCursor!=null){
while (mCursor.moveToNext()) {
// 获取图片的路径
String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA));
int size = mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media.SIZE))/1024;
String displayName = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
//用于展示相册初始化界面
mediaBeen.add(new MediaBean(MediaBean.Type.Image,path,size,displayName));
// 获取该图片的父路径名
String dirPath = new File(path).getParentFile().getAbsolutePath();
//存储对应关系
if (allPhotosTemp.containsKey(dirPath)) {
List<MediaBean> data = allPhotosTemp.get(dirPath);
data.add(new MediaBean(MediaBean.Type.Image,path,size,displayName));
continue;
} else {
List<MediaBean> data = new ArrayList<>();
data.add(new MediaBean(MediaBean.Type.Image,path,size,displayName));
allPhotosTemp.put(dirPath,data);
}
}
mCursor.close();
}
//更新界面
runOnUiThread(new Runnable() {
@Override
public void run() {
//...
}
});
}
}).start();
}
有四点需要注意:
- MediaBean是文件实体类,代码就不贴了
- 照片集合不是放在List<MediaBean>这样存储的,而是HashMap<String,List<MediaBean>>,这样把图片已文件夹(也就是父目录)分类,更节省内存,其次支持相册展示不同文件夹的照片
- 貌似没办法获取当前设备的拍照默认路径,有的设备是/DCIM,有的是/100andro还有/camera,那相册就默认展示最近所有照片吧。然后给用户列出一个文件夹列表让他选,这时可以把这几个文件夹放到最前面展示,算是小优化吧。
- 系统会时刻检测数据变化,有新的照片这个数据库会自动更新,不需干预。
视频相册
获取视频文件和上面基本一样,不过改下查询条件就行了,实际中有个问题:视频封面的获取。
首先视频封面缩略图在这个videothumbnails数据库,照片缩略图在thumbnails,对应到本地SD卡就是在sdcard/DCIM/.thumbnails/文件夹(有的设备可能不同)
PS:这个文件夹是隐藏的,so你知道你的手机为何存储空间越来越小了吧,拍的照片缩略图全在这儿。。。非常非常多
实际中发现读取不到新录制的视频封面,需要手动调用一个方法,来生成这个封面然后才能在videothumbnails读取到:
参考:http://stackoverflow.com/questions/27903264/how-to-get-the-video-thumbnail-path-and-not-the-bitmap
//videoId是这个视频文件在数据库的ID MediaStore.Video.Thumbnails.getThumbnail(getContentResolver(), videoId, MediaStore.Video.Thumbnails.MICRO_KIND, null);
并且这里封面和视频不在一个数据库,需要在两个cursor来读取
我这里获取整个SD的mp4格式视频,代码段如下:
/**
* 获取手机中所有视频的信息
*/
private void getAllVideoInfos(){
new Thread(new Runnable() {
@Override
public void run() {
HashMap<String,List<MediaBean>> allPhotosTemp = new HashMap<>();//所有照片
Uri mImageUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] proj = { MediaStore.Video.Thumbnails._ID
, MediaStore.Video.Thumbnails.DATA
,MediaStore.Video.Media.DURATION
,MediaStore.Video.Media.SIZE
,MediaStore.Video.Media.DISPLAY_NAME
,MediaStore.Video.Media.DATE_MODIFIED};
Cursor mCursor = getContentResolver().query(mImageUri,
proj,
MediaStore.Video.Media.MIME_TYPE + "=?",
new String[]{"video/mp4"},
MediaStore.Video.Media.DATE_MODIFIED+" desc");
if(mCursor!=null){
while (mCursor.moveToNext()) {
// 获取视频的路径
int videoId = mCursor.getInt(mCursor.getColumnIndex(MediaStore.Video.Media._ID));
String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Video.Media.DATA));
int duration = mCursor.getInt(mCursor.getColumnIndex(MediaStore.Video.Media.DURATION));
long size = mCursor.getLong(mCursor.getColumnIndex(MediaStore.Video.Media.SIZE))/1024; //单位kb
if(size<0){
//某些设备获取size<0,直接计算
Log.e("dml","this video size < 0 " + path);
size = new File(path).length()/1024;
}
String displayName = mCursor.getString(mCursor.getColumnIndex(MediaStore.Video.Media.DISPLAY_NAME));
long modifyTime = mCursor.getLong(mCursor.getColumnIndex(MediaStore.Video.Media.DATE_MODIFIED));//暂未用到
//提前生成缩略图,再获取:http://stackoverflow.com/questions/27903264/how-to-get-the-video-thumbnail-path-and-not-the-bitmap
MediaStore.Video.Thumbnails.getThumbnail(getContentResolver(), videoId, MediaStore.Video.Thumbnails.MICRO_KIND, null);
String[] projection = { MediaStore.Video.Thumbnails._ID, MediaStore.Video.Thumbnails.DATA};
Cursor cursor = getContentResolver().query(MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI
, projection
, MediaStore.Video.Thumbnails.VIDEO_ID + "=?"
, new String[]{videoId+""}
, null);
String thumbPath = "";
while (cursor.moveToNext()){
thumbPath = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Thumbnails.DATA));
}
cursor.close();
// 获取该视频的父路径名
String dirPath = new File(path).getParentFile().getAbsolutePath();
//存储对应关系
if (allPhotosTemp.containsKey(dirPath)) {
List<MediaBean> data = allPhotosTemp.get(dirPath);
data.add(new MediaBean(MediaBean.Type.Video,path,thumbPath,duration,size,displayName));
continue;
} else {
List<MediaBean> data = new ArrayList<>();
data.add(new MediaBean(MediaBean.Type.Video,path,thumbPath,duration,size,displayName));
allPhotosTemp.put(dirPath,data);
}
}
mCursor.close();
}
//更新界面
runOnUiThread(new Runnable() {
@Override
public void run() {
//...
}
});
}
}).start();
}
后记
其实Android已经提供叫做CursorLoader的API做这个事情,不需要手动new 工作线程,使用起来很简单有需要可以对上面代码改造。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# android
# 读取相册照片
# 读取本地相册
# Android读取本地照片
# Android使用phonegap从相册里面获取照片(代码分享)
# 基于Android实现保存图片到本地并可以在相册中显示出来
# Android拍照保存在系统相册不显示的问题解决方法
# android照相、相册获取图片剪裁报错的解决方法
# Android实现读取相机(相册)图片并进行剪裁
# Android实现调用系统相册和拍照的Demo示例
# Android开发从相机或相册获取图片裁剪
# Android拍照和获取相册图片
# Android打开相机和相册实例代码
# Android实现保存图片到本地并在相册中显示
# 视频文件
# 机中
# 放在
# 就在
# 有个
# 在这个
# 让他
# 有很多
# 不需要
# 就不
# 你知道
# 能在
# 没办法
# 很简单
# 时就
# 不需
# 在这儿
# 这几个
# 可以利用
# 以对
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
网站制作大概多少钱一个,做一个平台网站大概多少钱?
JavaScript实现Fly Bird小游戏
Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】
HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】
Laravel Fortify是什么,和Jetstream有什么关系
如何用美橙互联一键搭建多站合一网站?
phpredis提高消息队列的实时性方法(推荐)
Python并发异常传播_错误处理解析【教程】
高端云建站费用究竟需要多少预算?
如何快速启动建站代理加盟业务?
微信推文制作网站有哪些,怎么做微信推文,急?
php在windows下怎么调试_phpwindows环境调试操作说明【操作】
Laravel Asset编译怎么配置_Laravel Vite前端构建工具使用
利用 Google AI 进行 YouTube 视频 SEO 描述优化
Laravel如何实现API版本控制_Laravel版本化API设计方案
如何登录建站主机?访问步骤全解析
北京的网站制作公司有哪些,哪个视频网站最好?
如何彻底卸载建站之星软件?
Linux系统运维自动化项目教程_Ansible批量管理实战
CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】
Laravel如何发送系统通知?(Notification渠道示例)
手机软键盘弹出时影响布局的解决方法
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
html5的keygen标签为什么废弃_替代方案说明【解答】
大连网站制作公司哪家好一点,大连买房网站哪个好?
C++用Dijkstra(迪杰斯特拉)算法求最短路径
Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】
Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】
长沙做网站要多少钱,长沙国安网络怎么样?
如何用5美元大硬盘VPS安全高效搭建个人网站?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
canvas 画布在主流浏览器中的尺寸限制详细介绍
Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
Java遍历集合的三种方式
jimdo怎样用html5做选项卡_jimdo选项卡html5实现与切换效果【指南】
Laravel如何为API生成Swagger或OpenAPI文档
google浏览器怎么清理缓存_谷歌浏览器清除缓存加速详细步骤
如何在阿里云购买域名并搭建网站?
油猴 教程,油猴搜脚本为什么会网页无法显示?
Laravel如何优化应用性能?(缓存和优化命令)
JS去除重复并统计数量的实现方法
laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法
Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程
Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
Laravel如何与Docker(Sail)协同开发?(环境搭建教程)
C#如何调用原生C++ COM对象详解

