Android读取本地照片和视频相册实例代码

前言

项目中经常要选择本地照片或者视频的需求,如果去扫描整个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 工作线程,使用起来很简单有需要可以对上面代码改造。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-08-02 12:55:11

Android读取本地照片和视频相册实例代码的相关文章

Android 读取assets和raw文件内容实例代码_Android

android之文件操作--读取assets和raw文件下的内容 1.分别创建assets文件夹和res/raw文件夹:(要注意的raw文件是在res下new,然后创建一个名字为raw的文件夹)       2.创建两个txt文件,复制到asset和raw文件夹中: 3.实现的效果: 4.实现代码: (1)布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android

Android 读取assets和raw文件内容实例代码

android之文件操作--读取assets和raw文件下的内容 1.分别创建assets文件夹和res/raw文件夹:(要注意的raw文件是在res下new,然后创建一个名字为raw的文件夹) 2.创建两个txt文件,复制到asset和raw文件夹中: 3.实现的效果: 4.实现代码: (1)布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="

读取照片-关于android的读取本地照片的问题

问题描述 关于android的读取本地照片的问题 麻烦各位大神给指点一下,我写了一个读取本地相册照片的小应用,很简单,结果它只能读出网上下载的图片,二用相机拍的照片读不出来,这是怎么回事呀... 解决方案 uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" 解决方案二: Android照片旋转问题android 照片拍照问题解决android照片溢出问题 解决方案三: 需要权限的,在manif

cursor-关于Android读取本地视频的一些问题,求大神指导指导。。。。。。

问题描述 关于Android读取本地视频的一些问题,求大神指导指导...... List<Video> list = null; if (context != null) { Cursor cursor = context.getContentResolver().query( MediaStore.Video.Media.EXTERNAL_CONTENT_URI null null null null); 使用这种方法查找到本地视频信息,但是当我使用 File file=new File(l

Android读取本地json文件的方法(解决显示乱码问题)_Android

本文实例讲述了Android读取本地json文件的方法.分享给大家供大家参考,具体如下: 1.读取本地JSON ,但是显示汉字乱码 public static String readLocalJson(Context context, String fileName){ String jsonString=""; String resultString=""; try { BufferedReader bufferedReader=new BufferedReade

Android高仿QQ6.0侧滑删除实例代码_Android

推荐阅读: 先给大家分享一下,侧滑删除,布局也就是前面一个item,然后有两个隐藏的按钮(TextView也可以),然后我们可以向左侧滑动,然后显示出来,然后对delete(删除键)实现监听,就可以了哈.好了那就来看看代码怎么实现的吧. 首先和之前一样 自定义View,初始化ViewDragHelper: package com.example.removesidepull; import android.content.Context; import android.support.v4.wi

java读取http请求中的body实例代码_java

在http请求中,有Header和Body之分,读取header使用request.getHeader("..."); 读取Body使用request.getReader(),但getReader获取的是BufferedReader,需要把它转换成字符串, 下面是转换的方法. public static String getBodyString(BufferedReader br) { String inputLine; String str = ""; try {

Android中文件的压缩和解压缩实例代码

使用场景 当我们在应用的Assets目录中需要加入文件时,可以直接将源文件放入,但这样会造成打包后的apk整体过大,此时就需要将放入的文件进行压缩.又如当我们需要从服务器中下载文件时,如果下载源文件耗时又消耗流量,较大文件需要压缩,可以使得传输效率大大提高.下面我们就学习下基本的文件压缩和解压缩.Java中提供了压缩和解压缩的输入输出流 public static void zip(String src,String dest) throwsIOException { //定义压缩输出流 Zip

Android TimeLine 时间节点轴的实现实例代码

整理文档,搜刮出一个Android TimeLine 时间节点轴的实现实例代码,稍微整理精简一下做下分享. 效果图 具体实现 (RecyclerView) 1.Adapter package com.haoren.timeline; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.vie