diff options
Diffstat (limited to 'src/com/android/gallery3d/data/LocalAlbum.java')
-rw-r--r-- | src/com/android/gallery3d/data/LocalAlbum.java | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/data/LocalAlbum.java b/src/com/android/gallery3d/data/LocalAlbum.java new file mode 100644 index 000000000..7b7015af6 --- /dev/null +++ b/src/com/android/gallery3d/data/LocalAlbum.java @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.data; + +import android.content.ContentResolver; +import android.content.res.Resources; +import android.database.Cursor; +import android.net.Uri; +import android.os.Environment; +import android.provider.MediaStore; +import android.provider.MediaStore.Images; +import android.provider.MediaStore.Images.ImageColumns; +import android.provider.MediaStore.Video; +import android.provider.MediaStore.Video.VideoColumns; + +import com.android.gallery3d.R; +import com.android.gallery3d.app.GalleryApp; +import com.android.gallery3d.common.Utils; +import com.android.gallery3d.util.BucketNames; +import com.android.gallery3d.util.GalleryUtils; +import com.android.gallery3d.util.MediaSetUtils; + +import java.io.File; +import java.util.ArrayList; + +// LocalAlbumSet lists all media items in one bucket on local storage. +// The media items need to be all images or all videos, but not both. +public class LocalAlbum extends MediaSet { + private static final String TAG = "LocalAlbum"; + private static final String[] COUNT_PROJECTION = { "count(*)" }; + + private static final int INVALID_COUNT = -1; + private final String mWhereClause; + private final String mOrderClause; + private final Uri mBaseUri; + private final String[] mProjection; + + private final GalleryApp mApplication; + private final ContentResolver mResolver; + private final int mBucketId; + private final String mName; + private final boolean mIsImage; + private final ChangeNotifier mNotifier; + private final Path mItemPath; + private int mCachedCount = INVALID_COUNT; + + public LocalAlbum(Path path, GalleryApp application, int bucketId, + boolean isImage, String name) { + super(path, nextVersionNumber()); + mApplication = application; + mResolver = application.getContentResolver(); + mBucketId = bucketId; + mName = name; + mIsImage = isImage; + + if (isImage) { + mWhereClause = ImageColumns.BUCKET_ID + " = ?"; + mOrderClause = ImageColumns.DATE_TAKEN + " DESC, " + + ImageColumns._ID + " DESC"; + mBaseUri = Images.Media.EXTERNAL_CONTENT_URI; + mProjection = LocalImage.PROJECTION; + mItemPath = LocalImage.ITEM_PATH; + } else { + mWhereClause = VideoColumns.BUCKET_ID + " = ?"; + mOrderClause = VideoColumns.DATE_TAKEN + " DESC, " + + VideoColumns._ID + " DESC"; + mBaseUri = Video.Media.EXTERNAL_CONTENT_URI; + mProjection = LocalVideo.PROJECTION; + mItemPath = LocalVideo.ITEM_PATH; + } + + mNotifier = new ChangeNotifier(this, mBaseUri, application); + } + + public LocalAlbum(Path path, GalleryApp application, int bucketId, + boolean isImage) { + this(path, application, bucketId, isImage, + BucketHelper.getBucketName( + application.getContentResolver(), bucketId)); + } + + @Override + public boolean isCameraRoll() { + return mBucketId == MediaSetUtils.CAMERA_BUCKET_ID; + } + + @Override + public Uri getContentUri() { + if (mIsImage) { + return MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon() + .appendQueryParameter(LocalSource.KEY_BUCKET_ID, + String.valueOf(mBucketId)).build(); + } else { + return MediaStore.Video.Media.EXTERNAL_CONTENT_URI.buildUpon() + .appendQueryParameter(LocalSource.KEY_BUCKET_ID, + String.valueOf(mBucketId)).build(); + } + } + + @Override + public ArrayList<MediaItem> getMediaItem(int start, int count) { + DataManager dataManager = mApplication.getDataManager(); + Uri uri = mBaseUri.buildUpon() + .appendQueryParameter("limit", start + "," + count).build(); + ArrayList<MediaItem> list = new ArrayList<MediaItem>(); + GalleryUtils.assertNotInRenderThread(); + Cursor cursor = mResolver.query( + uri, mProjection, mWhereClause, + new String[]{String.valueOf(mBucketId)}, + mOrderClause); + if (cursor == null) { + Log.w(TAG, "query fail: " + uri); + return list; + } + + try { + while (cursor.moveToNext()) { + int id = cursor.getInt(0); // _id must be in the first column + Path childPath = mItemPath.getChild(id); + MediaItem item = loadOrUpdateItem(childPath, cursor, + dataManager, mApplication, mIsImage); + list.add(item); + } + } finally { + cursor.close(); + } + return list; + } + + private static MediaItem loadOrUpdateItem(Path path, Cursor cursor, + DataManager dataManager, GalleryApp app, boolean isImage) { + synchronized (DataManager.LOCK) { + LocalMediaItem item = (LocalMediaItem) dataManager.peekMediaObject(path); + if (item == null) { + if (isImage) { + item = new LocalImage(path, app, cursor); + } else { + item = new LocalVideo(path, app, cursor); + } + } else { + item.updateContent(cursor); + } + return item; + } + } + + // The pids array are sorted by the (path) id. + public static MediaItem[] getMediaItemById( + GalleryApp application, boolean isImage, ArrayList<Integer> ids) { + // get the lower and upper bound of (path) id + MediaItem[] result = new MediaItem[ids.size()]; + if (ids.isEmpty()) return result; + int idLow = ids.get(0); + int idHigh = ids.get(ids.size() - 1); + + // prepare the query parameters + Uri baseUri; + String[] projection; + Path itemPath; + if (isImage) { + baseUri = Images.Media.EXTERNAL_CONTENT_URI; + projection = LocalImage.PROJECTION; + itemPath = LocalImage.ITEM_PATH; + } else { + baseUri = Video.Media.EXTERNAL_CONTENT_URI; + projection = LocalVideo.PROJECTION; + itemPath = LocalVideo.ITEM_PATH; + } + + ContentResolver resolver = application.getContentResolver(); + DataManager dataManager = application.getDataManager(); + Cursor cursor = resolver.query(baseUri, projection, "_id BETWEEN ? AND ?", + new String[]{String.valueOf(idLow), String.valueOf(idHigh)}, + "_id"); + if (cursor == null) { + Log.w(TAG, "query fail" + baseUri); + return result; + } + try { + int n = ids.size(); + int i = 0; + + while (i < n && cursor.moveToNext()) { + int id = cursor.getInt(0); // _id must be in the first column + + // Match id with the one on the ids list. + if (ids.get(i) > id) { + continue; + } + + while (ids.get(i) < id) { + if (++i >= n) { + return result; + } + } + + Path childPath = itemPath.getChild(id); + MediaItem item = loadOrUpdateItem(childPath, cursor, dataManager, + application, isImage); + result[i] = item; + ++i; + } + return result; + } finally { + cursor.close(); + } + } + + public static Cursor getItemCursor(ContentResolver resolver, Uri uri, + String[] projection, int id) { + return resolver.query(uri, projection, "_id=?", + new String[]{String.valueOf(id)}, null); + } + + @Override + public int getMediaItemCount() { + if (mCachedCount == INVALID_COUNT) { + Cursor cursor = mResolver.query( + mBaseUri, COUNT_PROJECTION, mWhereClause, + new String[]{String.valueOf(mBucketId)}, null); + if (cursor == null) { + Log.w(TAG, "query fail"); + return 0; + } + try { + Utils.assertTrue(cursor.moveToNext()); + mCachedCount = cursor.getInt(0); + } finally { + cursor.close(); + } + } + return mCachedCount; + } + + @Override + public String getName() { + return getLocalizedName(mApplication.getResources(), mBucketId, mName); + } + + @Override + public long reload() { + if (mNotifier.isDirty()) { + mDataVersion = nextVersionNumber(); + mCachedCount = INVALID_COUNT; + } + return mDataVersion; + } + + @Override + public int getSupportedOperations() { + return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_INFO; + } + + @Override + public void delete() { + GalleryUtils.assertNotInRenderThread(); + mResolver.delete(mBaseUri, mWhereClause, + new String[]{String.valueOf(mBucketId)}); + } + + @Override + public boolean isLeafAlbum() { + return true; + } + + public static String getLocalizedName(Resources res, int bucketId, + String name) { + if (bucketId == MediaSetUtils.CAMERA_BUCKET_ID) { + return res.getString(R.string.folder_camera); + } else if (bucketId == MediaSetUtils.DOWNLOAD_BUCKET_ID) { + return res.getString(R.string.folder_download); + } else if (bucketId == MediaSetUtils.IMPORTED_BUCKET_ID) { + return res.getString(R.string.folder_imported); + } else if (bucketId == MediaSetUtils.SNAPSHOT_BUCKET_ID) { + return res.getString(R.string.folder_screenshot); + } else if (bucketId == MediaSetUtils.EDITED_ONLINE_PHOTOS_BUCKET_ID) { + return res.getString(R.string.folder_edited_online_photos); + } else { + return name; + } + } + + // Relative path is the absolute path minus external storage path + public static String getRelativePath(int bucketId) { + String relativePath = "/"; + if (bucketId == MediaSetUtils.CAMERA_BUCKET_ID) { + relativePath += BucketNames.CAMERA; + } else if (bucketId == MediaSetUtils.DOWNLOAD_BUCKET_ID) { + relativePath += BucketNames.DOWNLOAD; + } else if (bucketId == MediaSetUtils.IMPORTED_BUCKET_ID) { + relativePath += BucketNames.IMPORTED; + } else if (bucketId == MediaSetUtils.SNAPSHOT_BUCKET_ID) { + relativePath += BucketNames.SCREENSHOTS; + } else if (bucketId == MediaSetUtils.EDITED_ONLINE_PHOTOS_BUCKET_ID) { + relativePath += BucketNames.EDITED_ONLINE_PHOTOS; + } else { + // If the first few cases didn't hit the matching path, do a + // thorough search in the local directories. + File extStorage = Environment.getExternalStorageDirectory(); + String path = GalleryUtils.searchDirForPath(extStorage, bucketId); + if (path == null) { + Log.w(TAG, "Relative path for bucket id: " + bucketId + " is not found."); + relativePath = null; + } else { + relativePath = path.substring(extStorage.getAbsolutePath().length()); + } + } + return relativePath; + } + +} |