您好,登錄后才能下訂單哦!
前言
項目中經常要選擇本地照片或者視頻的需求,如果去掃描整個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(); }
有四點需要注意:
視頻相冊
獲取視頻文件和上面基本一樣,不過改下查詢條件就行了,實際中有個問題:視頻封面的獲取。
首先視頻封面縮略圖在這個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 工作線程,使用起來很簡單有需要可以對上面代碼改造。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。