/* * Copyright (C) 2013 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.photos.shims; import android.content.AsyncTaskLoader; import android.content.Context; import android.database.Cursor; import android.database.MatrixCursor; import android.graphics.drawable.Drawable; import android.net.Uri; import android.provider.MediaStore.Files.FileColumns; import android.util.SparseArray; import com.android.gallery3d.data.ContentListener; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.data.MediaItem; import com.android.gallery3d.data.MediaObject; import com.android.gallery3d.data.MediaSet; import com.android.gallery3d.data.MediaSet.ItemConsumer; import com.android.gallery3d.data.MediaSet.SyncListener; import com.android.gallery3d.data.Path; import com.android.gallery3d.util.Future; import com.android.photos.data.PhotoSetLoader; import java.util.ArrayList; /** * Returns all MediaItems in a MediaSet, wrapping them in a cursor to appear * like a PhotoSetLoader */ public class MediaItemsLoader extends AsyncTaskLoader implements LoaderCompatShim { private static final SyncListener sNullListener = new SyncListener() { @Override public void onSyncDone(MediaSet mediaSet, int resultCode) { } }; private final MediaSet mMediaSet; private final DataManager mDataManager; private Future mSyncTask = null; private ContentListener mObserver = new ContentListener() { @Override public void onContentDirty() { onContentChanged(); } }; private SparseArray mMediaItems; public MediaItemsLoader(Context context) { super(context); mDataManager = DataManager.from(context); String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL); mMediaSet = mDataManager.getMediaSet(path); } public MediaItemsLoader(Context context, String parentPath) { super(context); mDataManager = DataManager.from(getContext()); mMediaSet = mDataManager.getMediaSet(parentPath); } @Override protected void onStartLoading() { super.onStartLoading(); mMediaSet.addContentListener(mObserver); mSyncTask = mMediaSet.requestSync(sNullListener); forceLoad(); } @Override protected boolean onCancelLoad() { if (mSyncTask != null) { mSyncTask.cancel(); mSyncTask = null; } return super.onCancelLoad(); } @Override protected void onStopLoading() { super.onStopLoading(); cancelLoad(); mMediaSet.removeContentListener(mObserver); } @Override protected void onReset() { super.onReset(); onStopLoading(); } @Override public Cursor loadInBackground() { // TODO: This probably doesn't work mMediaSet.reload(); final MatrixCursor cursor = new MatrixCursor(PhotoSetLoader.PROJECTION); final Object[] row = new Object[PhotoSetLoader.PROJECTION.length]; final SparseArray mediaItems = new SparseArray(); mMediaSet.enumerateTotalMediaItems(new ItemConsumer() { @Override public void consume(int index, MediaItem item) { row[PhotoSetLoader.INDEX_ID] = index; row[PhotoSetLoader.INDEX_DATA] = item.getContentUri().toString(); row[PhotoSetLoader.INDEX_DATE_ADDED] = item.getDateInMs(); row[PhotoSetLoader.INDEX_HEIGHT] = item.getHeight(); row[PhotoSetLoader.INDEX_WIDTH] = item.getWidth(); row[PhotoSetLoader.INDEX_WIDTH] = item.getWidth(); int rawMediaType = item.getMediaType(); int mappedMediaType = FileColumns.MEDIA_TYPE_NONE; if (rawMediaType == MediaItem.MEDIA_TYPE_IMAGE) { mappedMediaType = FileColumns.MEDIA_TYPE_IMAGE; } else if (rawMediaType == MediaItem.MEDIA_TYPE_VIDEO) { mappedMediaType = FileColumns.MEDIA_TYPE_VIDEO; } row[PhotoSetLoader.INDEX_MEDIA_TYPE] = mappedMediaType; row[PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS] = item.getSupportedOperations(); cursor.addRow(row); mediaItems.append(index, item); } }); synchronized (mMediaSet) { mMediaItems = mediaItems; } return cursor; } @Override public Drawable drawableForItem(Cursor item, Drawable recycle) { BitmapJobDrawable drawable = null; if (recycle == null || !(recycle instanceof BitmapJobDrawable)) { drawable = new BitmapJobDrawable(); } else { drawable = (BitmapJobDrawable) recycle; } int index = item.getInt(PhotoSetLoader.INDEX_ID); drawable.setMediaItem(mMediaItems.get(index)); return drawable; } public static int getThumbnailSize() { return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); } @Override public Uri uriForItem(Cursor item) { int index = item.getInt(PhotoSetLoader.INDEX_ID); MediaItem mi = mMediaItems.get(index); return mi == null ? null : mi.getContentUri(); } @Override public ArrayList urisForSubItems(Cursor item) { return null; } @Override public void deleteItemWithPath(Object path) { MediaObject o = mDataManager.getMediaObject((Path) path); if (o != null) { o.delete(); } } @Override public Object getPathForItem(Cursor item) { int index = item.getInt(PhotoSetLoader.INDEX_ID); MediaItem mi = mMediaItems.get(index); if (mi != null) { return mi.getPath(); } return null; } }