全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

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();
 }

有四点需要注意:

  1. MediaBean是文件实体类,代码就不贴了
  2. 照片集合不是放在List<MediaBean>这样存储的,而是HashMap<String,List<MediaBean>>,这样把图片已文件夹(也就是父目录)分类,更节省内存,其次支持相册展示不同文件夹的照片
  3. 貌似没办法获取当前设备的拍照默认路径,有的设备是/DCIM,有的是/100andro还有/camera,那相册就默认展示最近所有照片吧。然后给用户列出一个文件夹列表让他选,这时可以把这几个文件夹放到最前面展示,算是小优化吧。
  4. 系统会时刻检测数据变化,有新的照片这个数据库会自动更新,不需干预。

视频相册

获取视频文件和上面基本一样,不过改下查询条件就行了,实际中有个问题:视频封面的获取。

首先视频封面缩略图在这个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实现保存图片到本地并在相册中显示  # 视频文件  # 机中  # 放在  # 就在  # 有个  # 在这个  # 让他  # 有很多  # 不需要  # 就不  # 你知道  # 能在  # 没办法  # 很简单  # 时就  # 不需  # 在这儿  # 这几个  # 可以利用  # 以对 


相关文章: 定制建站策划方案_专业建站与网站建设方案一站式指南  香港服务器如何优化才能显著提升网站加载速度?  小建面朝正北,A点实际方位是否存在偏差?  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  linux top下的 minerd 木马清除方法  常州自助建站工具推荐:低成本搭建与模板选择技巧  山东网站制作公司有哪些,山东大源集团官网?  如何快速查询网站的真实建站时间?  动图在线制作网站有哪些,滑动动图图集怎么做?  深圳 网站制作,深圳招聘网站哪个比较好一点啊?  如何选择香港主机高效搭建外贸独立站?  如何配置支付宝与微信支付功能?  建站之星代理如何获取技术支持?  如何在服务器上三步完成建站并提升流量?  建站一年半SEO优化实战指南:核心词挖掘与长尾流量提升策略  行程制作网站有哪些,第三方机票电子行程单怎么开?  建站主机选购指南:核心配置优化与品牌推荐方案  如何获取免费开源的自助建站系统源码?  公司网站的制作公司,企业网站制作基本流程有哪些?  微信h5制作网站有哪些,免费微信H5页面制作工具?  免费制作小说封面的网站有哪些,怎么接网站批量的封面单?  ,怎么用自己头像做动态表情包?  如何快速搭建高效可靠的建站解决方案?  企业网站制作费用多少,企业网站空间一般需要多大,费用是多少?  网站网页制作电话怎么打,怎样安装和使用钉钉软件免费打电话?  定制建站方案优化指南:企业官网开发与建站费用解析  如何正确选择百度移动适配建站域名?  建站之星如何修改网站生成路径?  湖北网站制作公司有哪些,湖北清能集团官网?  定制建站是什么?如何实现个性化需求?  javascript中的try catch异常捕获机制用法分析  如何用IIS7快速搭建并优化网站站点?  如何在搬瓦工VPS快速搭建网站?  如何基于云服务器快速搭建个人网站?  建站之星体验版:智能建站系统+响应式设计,多端适配快速建站  制作国外网站的软件,国外有哪些比较优质的网站推荐?  如何零基础在云服务器搭建WordPress站点?  网站好制作吗知乎,网站开发好学吗?有什么技巧?  广德云建站网站建设方案与建站流程优化指南  C++如何使用std::optional?(处理可选值)  简单实现Android文件上传  网站制作员失业,怎样查看自己网站的注册者?  建站主机CVM配置优化、SEO策略与性能提升指南  建站主机数据库如何配置才能提升网站性能?  jQuery 常见小例汇总  建站之星代理费用多少?最新价格详情介绍  Python文件管理规范_工程实践说明【指导】  家庭服务器如何搭建个人网站?  小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。