系统相册会调用android的隐藏api。因此,直接编译会报错。需要导入系统包:framework_intermediates/classes.jar (android的框架类) 网上一搜就能搜到。把包作为user liblary引用到项目中来,在解决一些版本兼容问题,就可以编译了。不过上面我编译的代码,把调用系统隐藏api的地方改成了替代代码,其他兼容错误也解决了,可以直接编译,运行起来可能会有问题。可以根据相应问题来解决。
1.获取数据
a.文件夹列表
相册的数据当然是媒体数据,包括图片和视频。相册的文件夹列表除了实际的图片文件夹分类,相册还添加了相机图片、相机视频、所有图片、所有视频几个分类。
这些分类数据也以图片文件夹的形式列出来。文件夹列表的数据是怎么获取的呢,当然,可以自己到sdcard中去找,当然这就2了。系统将这个工作已经做了,系统会维护一个Media数据库来存储这些媒体数据信息。以前自己也使用过Media数据库来查找媒体数据信息,看了相册使用Media数据库,瞬间感觉自己的方式弱爆了。
相册的列表页面是GalleryPicker,当加载列表数据的时候会执行下面这个方法:
复制代码
下面是获取系统媒体列表数据,列表有5类,包括相机图片、相机视频、相机媒体(相机图片+相机视频)、所有图片、所有视频
复制代码
里面抽象定义的数据比较多,这里介绍不可能太清楚。可以取看看代码,仔细研究一下。总体说来,这里得到相机图片、相机视频、相机媒体(相机图片+相机视频)、所有图片、所有视频这几种数据的列表。列表的结构是ImageList、VideoList等,它们都是BaseImageList的子类,代码在com.android.camera.gallery包下面。
下面是获取sdcard文件夹列表数据
复制代码
上面的全部都是招式,下面才是内功,也就是获取列表的核心部分,由于相册把这一块做了很多抽象,因此,我把核心的代码整理出来
复制代码
1.获取数据
a.文件夹列表
相册的数据当然是媒体数据,包括图片和视频。相册的文件夹列表除了实际的图片文件夹分类,相册还添加了相机图片、相机视频、所有图片、所有视频几个分类。
这些分类数据也以图片文件夹的形式列出来。文件夹列表的数据是怎么获取的呢,当然,可以自己到sdcard中去找,当然这就2了。系统将这个工作已经做了,系统会维护一个Media数据库来存储这些媒体数据信息。以前自己也使用过Media数据库来查找媒体数据信息,看了相册使用Media数据库,瞬间感觉自己的方式弱爆了。
相册的列表页面是GalleryPicker,当加载列表数据的时候会执行下面这个方法:
- private void workerRun() {
- ArrayList<Item> allItems = new ArrayList<Item>();
- checkScanning();//检查系统Media库扫描后台是否还在执行
- .....
- checkImageList(allItems);//获取系统媒体数据列表,这里就包括所有的图片文件夹列表、相机图片、相机视频、所有图片、所有视频
- .....
- checkBucketIds(allItems);//下面是获取sdcard文件夹列表数据 ps:个人觉得这个方法和上面的checkImageList方法的名字很有歧义啊。根据方法名很容易理解为checkImageList是先获取整个列表,checkBucketIds方法是获取列表需要的数据。被名字忽悠了。应该叫做checkInternalList 和 checkExternalList嘛。
- checkThumbBitmap(allItems);
- checkLowStorage();
- }
下面是获取系统媒体列表数据,列表有5类,包括相机图片、相机视频、相机媒体(相机图片+相机视频)、所有图片、所有视频
- private void checkImageList(ArrayList<Item> allItems) {
- int length = IMAGE_LIST_DATA.length;//5类列表的数据全部定义在IMAGE_LIST_DATA里面
- IImageList[] lists = new IImageList[length];
- for (int i = 0; i < length; i++) {
- ImageListData data = IMAGE_LIST_DATA[i];
- lists[i] = createImageList(data.mInclude, data.mBucketId,
- getContentResolver());
- .....
- Item item = new Item(data.mType, data.mBucketId, getResources()
- .getString(data.mStringId), lists[i]);
- allItems.add(item);
- final Item finalItem = item;
- mHandler.post(new Runnable() {
- public void run() {
- updateItem(finalItem);
- }
- });
- }
- }
里面抽象定义的数据比较多,这里介绍不可能太清楚。可以取看看代码,仔细研究一下。总体说来,这里得到相机图片、相机视频、相机媒体(相机图片+相机视频)、所有图片、所有视频这几种数据的列表。列表的结构是ImageList、VideoList等,它们都是BaseImageList的子类,代码在com.android.camera.gallery包下面。
下面是获取sdcard文件夹列表数据
- private void checkBucketIds(ArrayList<Item> allItems) {
- final IImageList allImages;
- //获取所有数据列表
- if (!mScanning && !mUnmounted) {
- allImages = ImageManager.makeImageList(getContentResolver(),
- ImageManager.DataLocation.ALL, ImageManager.INCLUDE_IMAGES
- | ImageManager.INCLUDE_VIDEOS,
- ImageManager.SORT_DESCENDING, null);
- } else {
- allImages = ImageManager.makeEmptyImageList();
- }
- .....
- //这个地方这句话,是比较屌的,直接就查到了sdcard中的文件夹列表。以前,自己写这一块。就很2地取Media数据库,把所有的图片文件路径读出来,在来截取生成列表。相册是不是这样写的,具体,下面会介绍
- HashMap<String, String> hashMap = allImages.getBucketIds();
- allImages.close();
- for (Map.Entry<String, String> entry : hashMap.entrySet()) {
- String key = entry.getKey();
- if (!key.equals(CAMERA_BUCKET)) {
- IImageList list = createImageList(ImageManager.INCLUDE_IMAGES
- | ImageManager.INCLUDE_VIDEOS, key,
- getContentResolver());
- .....
- Item item = new Item(Item.TYPE_NORMAL_FOLDERS, key,
- entry.getValue(), list);
- allItems.add(item);
- final Item finalItem = item;
- mHandler.post(new Runnable() {
- public void run() {
- updateItem(finalItem);
- }
- });
- }
- }
- mHandler.post(new Runnable() {
- public void run() {
- checkBucketIdsFinished();
- }
- });
- }
上面的全部都是招式,下面才是内功,也就是获取列表的核心部分,由于相册把这一块做了很多抽象,因此,我把核心的代码整理出来
- package com.example.demo;
- import java.util.HashMap;
- import android.content.ContentResolver;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Environment;
- import android.provider.MediaStore.Images;
- import android.provider.MediaStore.Images.Media;
- /**
- * 获取系统Midia数据库数据,Midia数据库要这么用
- *
- * @author johnnyxyz
- * @mail johnnyxyzw@gmail.com
- */
- public class MediaListGetter {
- public static final Uri EXTERNAL_STORAGE_URI = Images.Media.EXTERNAL_CONTENT_URI;
- public static final Uri INTERNAL_STORAGE_URI = Images.Media.INTERNAL_CONTENT_URI;
- public static final Uri VIDEO_STORAGE_URI = Uri.parse("content://media/external/video/media");
- private static final String[] ACCEPTABLE_IMAGE_TYPES = new String[] { "image/jpeg",
- "image/png", "image/gif" };
- private static final String WHERE_CLAUSE = "(" + Media.MIME_TYPE + " in (?, ?, ?))";
- private static final String WHERE_CLAUSE_WITH_BUCKET_ID = WHERE_CLAUSE + " AND "
- + Media.BUCKET_ID + " = ?";
- protected String whereClause(String bucketId) {
- return bucketId == null ? WHERE_CLAUSE : WHERE_CLAUSE_WITH_BUCKET_ID;
- }
- private String[] whereClauseArgs(String bucketId) {
- if (bucketId != null) {
- int count = ACCEPTABLE_IMAGE_TYPES.length;
- String[] result = new String[count + 1];
- System.arraycopy(ACCEPTABLE_IMAGE_TYPES, 0, result, 0, count);
- result[count] = bucketId;
- return result;
- }
- return ACCEPTABLE_IMAGE_TYPES;
- }
- public static final String CAMERA_IMAGE_BUCKET_NAME = Environment.getExternalStorageDirectory()
- .toString() + "/DCIM/Camera";
- public static final String CAMERA_IMAGE_BUCKET_ID = String.valueOf(CAMERA_IMAGE_BUCKET_NAME
- .toLowerCase().hashCode());
- public MediaListGetter(ContentResolver mContentResolver) {
- super();
- this.mContentResolver = mContentResolver;
- }
- private final ContentResolver mContentResolver;
- /**
- * 获取所有Camera图片文件夾列表
- * @return
- */
- public HashMap<String, String> getCameraImages() {
- // 内置存储的图片
- Uri baseUri = INTERNAL_STORAGE_URI;
- Uri uri = baseUri.buildUpon().appendQueryParameter("distinct", "true").build();
- Cursor internal = Media.query(mContentResolver, uri, new String[] {
- Media.BUCKET_DISPLAY_NAME, Media.BUCKET_ID }, whereClause(CAMERA_IMAGE_BUCKET_ID),
- whereClauseArgs(CAMERA_IMAGE_BUCKET_ID), null);
- // 外置存储的图片
- baseUri = EXTERNAL_STORAGE_URI;
- uri = baseUri.buildUpon().appendQueryParameter("distinct", "true").build();
- Cursor external = Media.query(mContentResolver, uri, new String[] {
- Media.BUCKET_DISPLAY_NAME, Media.BUCKET_ID }, whereClause(CAMERA_IMAGE_BUCKET_ID),
- whereClauseArgs(CAMERA_IMAGE_BUCKET_ID), null);
- try {
- HashMap<String, String> hash = new HashMap<String, String>();
- while (internal.moveToNext()) {
- hash.put(internal.getString(1), internal.getString(0));
- }
- while (external.moveToNext()) {
- hash.put(external.getString(1), external.getString(0));
- }
- return hash;
- } finally {
- internal.close();
- external.close();
- }
- }
- /**
- * 获取所有Camera视频文件夾列表
- * @return
- */
- public HashMap<String, String> getCameraVidios() {
- Uri baseUri = VIDEO_STORAGE_URI;
- Uri uri = baseUri.buildUpon().appendQueryParameter("distinct", "true").build();
- Cursor cursor = Media.query(mContentResolver, uri, new String[] {
- Media.BUCKET_DISPLAY_NAME, Media.BUCKET_ID },
- (CAMERA_IMAGE_BUCKET_ID != null ? Images.Media.BUCKET_ID + " = '"
- + CAMERA_IMAGE_BUCKET_ID + "'" : null), null, null);
- try {
- HashMap<String, String> hash = new HashMap<String, String>();
- while (cursor.moveToNext()) {
- hash.put(cursor.getString(1), cursor.getString(0));
- }
- return hash;
- } finally {
- cursor.close();
- }
- };
- /**
- * 获取所有Camera媒体文件夾列表
- * @return
- */
- public void getCameraMedias() {
- // getCameraVidios + getCameraImages
- };
- /**
- * 获取所有圖片的文件夾列表
- * @return
- */
- public HashMap<String, String> getAllImages() {
- Uri baseUri = EXTERNAL_STORAGE_URI;
- Uri uri = baseUri.buildUpon().appendQueryParameter("distinct", "true").build();
- // 外置存储camera图片
- Cursor camera = Media.query(mContentResolver, uri, new String[] {
- Media.BUCKET_DISPLAY_NAME, Media.BUCKET_ID }, whereClause(CAMERA_IMAGE_BUCKET_ID),
- whereClauseArgs(CAMERA_IMAGE_BUCKET_ID), null);
- // 外置存储非camera图片
- Cursor external = Media.query(mContentResolver, uri, new String[] {
- Media.BUCKET_DISPLAY_NAME, Media.BUCKET_ID }, whereClause(null),
- whereClauseArgs(null), null);
- // 内置图片
- baseUri = INTERNAL_STORAGE_URI;
- uri = baseUri.buildUpon().appendQueryParameter("distinct", "true").build();
- Cursor internal = Media.query(mContentResolver, uri, new String[] {
- Media.BUCKET_DISPLAY_NAME, Media.BUCKET_ID }, whereClause(null),
- whereClauseArgs(null), null);
- try {
- HashMap<String, String> hash = new HashMap<String, String>();
- while (camera.moveToNext()) {
- hash.put(camera.getString(1), camera.getString(0));
- }
- while (external.moveToNext()) {
- hash.put(external.getString(1), external.getString(0));
- }
- while (internal.moveToNext()) {
- hash.put(internal.getString(1), internal.getString(0));
- }
- return hash;
- } finally {
- camera.close();
- external.close();
- internal.close();
- }
- };
- /**
- * 获取所有視頻的文件夾列表
- * @return
- */
- public HashMap<String, String> getAllVidios() {
- Uri baseUri = VIDEO_STORAGE_URI;
- Uri uri = baseUri.buildUpon().appendQueryParameter("distinct", "true").build();
- Cursor cursor = Media.query(mContentResolver, uri, new String[] {
- Media.BUCKET_DISPLAY_NAME, Media.BUCKET_ID }, null, null, null);
- try {
- HashMap<String, String> hash = new HashMap<String, String>();
- while (cursor.moveToNext()) {
- hash.put(cursor.getString(1), cursor.getString(0));
- }
- return hash;
- } finally {
- cursor.close();
- }
- };
- /**
- * 获取外置存储的所有文件夹
- * @return
- */
- public HashMap<String, String> getExternalFolders() {
- Uri baseUri = EXTERNAL_STORAGE_URI;
- Uri uri = baseUri.buildUpon().appendQueryParameter("distinct", "true").build();
- Cursor cursor = Media.query(mContentResolver, uri, new String[] {
- Media.BUCKET_DISPLAY_NAME, Media.BUCKET_ID }, null, null, null);
- try {
- HashMap<String, String> hash = new HashMap<String, String>();
- while (cursor.moveToNext()) {
- if (CAMERA_IMAGE_BUCKET_ID.equals(cursor.getString(1)))
- continue;
- hash.put(cursor.getString(1), cursor.getString(0));
- }
- return hash;
- } finally {
- cursor.close();
- }
- }
- }