| /* |
| * Copyright (C) 2007 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.camera; |
| |
| import android.app.Activity; |
| import android.app.Dialog; |
| import android.app.ProgressDialog; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.content.SharedPreferences; |
| import android.content.res.Resources; |
| import android.graphics.Bitmap; |
| import android.graphics.Canvas; |
| import android.graphics.Matrix; |
| import android.graphics.Paint; |
| import android.graphics.Rect; |
| import android.graphics.drawable.Drawable; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.os.Environment; |
| import android.os.Handler; |
| import android.os.StatFs; |
| import android.preference.PreferenceManager; |
| import android.provider.MediaStore.Images; |
| import android.util.Config; |
| import android.util.Log; |
| import android.util.SparseArray; |
| import android.view.ContextMenu; |
| import android.view.LayoutInflater; |
| import android.view.Menu; |
| import android.view.MenuItem; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.MenuItem.OnMenuItemClickListener; |
| import android.widget.AdapterView; |
| import android.widget.BaseAdapter; |
| import android.widget.GridView; |
| import android.widget.TextView; |
| import android.widget.Toast; |
| import android.widget.AdapterView.AdapterContextMenuInfo; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| public class GalleryPicker extends Activity { |
| static private final String TAG = "GalleryPicker"; |
| |
| GridView mGridView; |
| Drawable mFrameGalleryMask; |
| Drawable mCellOutline; |
| Drawable mVideoOverlay; |
| |
| BroadcastReceiver mReceiver; |
| GalleryPickerAdapter mAdapter; |
| |
| Dialog mMediaScanningDialog; |
| |
| MenuItem mFlipItem; |
| SharedPreferences mPrefs; |
| |
| boolean mPausing = false; |
| |
| private static long LOW_STORAGE_THRESHOLD = 1024 * 1024 * 2; |
| |
| public GalleryPicker() { |
| } |
| |
| private void rebake(boolean unmounted, boolean scanning) { |
| if (mMediaScanningDialog != null) { |
| mMediaScanningDialog.cancel(); |
| mMediaScanningDialog = null; |
| } |
| if (scanning) { |
| mMediaScanningDialog = ProgressDialog.show( |
| this, |
| null, |
| getResources().getString(R.string.wait), |
| true, |
| true); |
| } |
| mAdapter.notifyDataSetChanged(); |
| mAdapter.init(!unmounted && !scanning); |
| } |
| |
| @Override |
| public void onCreate(Bundle icicle) { |
| super.onCreate(icicle); |
| |
| mPrefs = PreferenceManager.getDefaultSharedPreferences(this); |
| |
| setContentView(R.layout.gallerypicker); |
| |
| mGridView = (GridView) findViewById(R.id.albums); |
| mGridView.setSelector(android.R.color.transparent); |
| |
| mReceiver = new BroadcastReceiver() { |
| |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| if (Config.LOGV) Log.v(TAG, "onReceiveIntent " + intent.getAction()); |
| String action = intent.getAction(); |
| if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { |
| // SD card available |
| // TODO put up a "please wait" message |
| // TODO also listen for the media scanner finished message |
| } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) { |
| // SD card unavailable |
| if (Config.LOGV) Log.v(TAG, "sd card no longer available"); |
| Toast.makeText(GalleryPicker.this, getResources().getString(R.string.wait), 5000); |
| rebake(true, false); |
| } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) { |
| Toast.makeText(GalleryPicker.this, getResources().getString(R.string.wait), 5000); |
| rebake(false, true); |
| } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) { |
| if (Config.LOGV) |
| Log.v(TAG, "rebake because of ACTION_MEDIA_SCANNER_FINISHED"); |
| rebake(false, false); |
| } else if (action.equals(Intent.ACTION_MEDIA_EJECT)) { |
| if (Config.LOGV) |
| Log.v(TAG, "rebake because of ACTION_MEDIA_EJECT"); |
| rebake(true, false); |
| } |
| } |
| }; |
| |
| mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { |
| public void onItemClick(AdapterView<?> parent, View view, int position, long id) { |
| launchFolderGallery(position); |
| } |
| }); |
| mGridView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { |
| public void onCreateContextMenu(ContextMenu menu, View v, final ContextMenu.ContextMenuInfo menuInfo) { |
| int position = ((AdapterContextMenuInfo)menuInfo).position; |
| menu.setHeaderTitle(mAdapter.baseTitleForPosition(position)); |
| if ((mAdapter.getIncludeMediaTypes(position) & ImageManager.INCLUDE_IMAGES) != 0) { |
| menu.add(0, 207, 0, R.string.slide_show) |
| .setOnMenuItemClickListener(new OnMenuItemClickListener() { |
| public boolean onMenuItemClick(MenuItem item) { |
| AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo; |
| int position = info.position; |
| |
| Uri targetUri; |
| synchronized (mAdapter.mItems) { |
| if (position < 0 || position >= mAdapter.mItems.size()) { |
| return true; |
| } |
| // the mFirstImageUris list includes the "all" uri |
| targetUri = mAdapter.mItems.get(position).mFirstImageUri; |
| } |
| if (targetUri != null && position > 0) { |
| targetUri = targetUri.buildUpon().appendQueryParameter("bucketId", |
| mAdapter.mItems.get(info.position).mId).build(); |
| } |
| // Log.v(TAG, "URI to launch slideshow " + targetUri); |
| Intent intent = new Intent(Intent.ACTION_VIEW, targetUri); |
| intent.putExtra("slideshow", true); |
| startActivity(intent); |
| return true; |
| } |
| }); |
| } |
| menu.add(0, 208, 0, R.string.view) |
| .setOnMenuItemClickListener(new OnMenuItemClickListener() { |
| public boolean onMenuItemClick(MenuItem item) { |
| AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo; |
| launchFolderGallery(info.position); |
| return true; |
| } |
| }); |
| } |
| }); |
| } |
| |
| private void launchFolderGallery(int position) { |
| mAdapter.mItems.get(position).launch(this); |
| } |
| |
| class ItemInfo { |
| Bitmap bitmap; |
| int count; |
| } |
| |
| static class Item implements Comparable<Item>{ |
| // The type is also used as the sort order |
| public final static int TYPE_ALL_IMAGES = 0; |
| public final static int TYPE_ALL_VIDEOS = 1; |
| public final static int TYPE_CAMERA_IMAGES = 2; |
| public final static int TYPE_CAMERA_VIDEOS = 3; |
| public final static int TYPE_NORMAL_FOLDERS = 4; |
| |
| public int mType; |
| public String mId; |
| public String mName; |
| public Uri mFirstImageUri; |
| public ItemInfo mThumb; |
| |
| public Item(int type, String id, String name) { |
| mType = type; |
| mId = id; |
| mName = name; |
| } |
| |
| public boolean needsBucketId() { |
| return mType >= TYPE_CAMERA_IMAGES; |
| } |
| |
| public void launch(Activity activity) { |
| android.net.Uri uri = Images.Media.INTERNAL_CONTENT_URI; |
| if (needsBucketId()) { |
| uri = uri.buildUpon().appendQueryParameter("bucketId",mId).build(); |
| } |
| Intent intent = new Intent(Intent.ACTION_VIEW, uri); |
| intent.putExtra("windowTitle", mName); |
| intent.putExtra("mediaTypes", getIncludeMediaTypes()); |
| activity.startActivity(intent); |
| } |
| |
| public int getIncludeMediaTypes() { |
| return convertItemTypeToIncludedMediaType(mType); |
| } |
| |
| public static int convertItemTypeToIncludedMediaType(int itemType) { |
| switch (itemType) { |
| case TYPE_ALL_IMAGES: |
| case TYPE_CAMERA_IMAGES: |
| return ImageManager.INCLUDE_IMAGES; |
| case TYPE_ALL_VIDEOS: |
| case TYPE_CAMERA_VIDEOS: |
| return ImageManager.INCLUDE_VIDEOS; |
| case TYPE_NORMAL_FOLDERS: |
| default: |
| return ImageManager.INCLUDE_IMAGES | ImageManager.INCLUDE_VIDEOS; |
| } |
| } |
| |
| public int getOverlay() { |
| switch (mType) { |
| case TYPE_ALL_IMAGES: |
| case TYPE_CAMERA_IMAGES: |
| return R.drawable.frame_overlay_gallery_camera; |
| case TYPE_ALL_VIDEOS: |
| case TYPE_CAMERA_VIDEOS: |
| return R.drawable.frame_overlay_gallery_video; |
| case TYPE_NORMAL_FOLDERS: |
| return R.drawable.frame_overlay_gallery_folder; |
| default: |
| return -1; |
| } |
| } |
| |
| // sort based on the sort order, then the case-insensitive display name, then the id. |
| public int compareTo(Item other) { |
| int x = mType - other.mType; |
| if (x == 0) { |
| x = mName.compareToIgnoreCase(other.mName); |
| if (x == 0) { |
| x = mId.compareTo(other.mId); |
| } |
| } |
| return x; |
| } |
| } |
| |
| class GalleryPickerAdapter extends BaseAdapter { |
| ArrayList<Item> mItems = new ArrayList<Item>(); |
| |
| boolean mDone = false; |
| CameraThread mWorkerThread; |
| |
| public void init(boolean assumeMounted) { |
| mItems.clear(); |
| |
| ImageManager.IImageList images; |
| if (assumeMounted) { |
| images = ImageManager.instance().allImages( |
| GalleryPicker.this, |
| getContentResolver(), |
| ImageManager.DataLocation.ALL, |
| ImageManager.INCLUDE_IMAGES | ImageManager.INCLUDE_VIDEOS, |
| ImageManager.SORT_DESCENDING); |
| } else { |
| images = ImageManager.instance().emptyImageList(); |
| } |
| |
| if (mWorkerThread != null) { |
| try { |
| mDone = true; |
| if (Config.LOGV) |
| Log.v(TAG, "about to call join on thread " + mWorkerThread.getId()); |
| mWorkerThread.join(); |
| } finally { |
| mWorkerThread = null; |
| } |
| } |
| |
| String cameraItem = ImageManager.CAMERA_IMAGE_BUCKET_ID; |
| final HashMap<String, String> hashMap = images.getBucketIds(); |
| String cameraBucketId = null; |
| for (Map.Entry<String, String> entry: hashMap.entrySet()) { |
| String key = entry.getKey(); |
| if (key == null) { |
| continue; |
| } |
| if (key.equals(cameraItem)) { |
| cameraBucketId = key; |
| } else { |
| mItems.add(new Item(Item.TYPE_NORMAL_FOLDERS, key, entry.getValue())); |
| } |
| } |
| images.deactivate(); |
| notifyDataSetInvalidated(); |
| |
| // If just one |
| addBucketIfNotEmpty(Item.TYPE_ALL_IMAGES, null, R.string.all_images); |
| addBucketIfNotEmpty(Item.TYPE_ALL_VIDEOS, null, R.string.all_videos); |
| |
| if (cameraBucketId != null) { |
| addBucketIfNotEmpty(Item.TYPE_CAMERA_IMAGES, cameraBucketId, |
| R.string.gallery_camera_bucket_name); |
| addBucketIfNotEmpty(Item.TYPE_CAMERA_VIDEOS, cameraBucketId, |
| R.string.gallery_camera_videos_bucket_name); |
| } |
| |
| java.util.Collections.sort(mItems); |
| |
| mDone = false; |
| mWorkerThread = new CameraThread(new Runnable() { |
| public void run() { |
| try { |
| // no images, nothing to do |
| if (mItems.size() == 0) |
| return; |
| |
| for (int i = 0; i < mItems.size() && !mDone; i++) { |
| final Item item = mItems.get(i); |
| ImageManager.IImageList list = createImageList( |
| item.getIncludeMediaTypes(), item.mId); |
| try { |
| if (mPausing) { |
| break; |
| } |
| if (list.getCount() > 0) |
| item.mFirstImageUri = list.getImageAt(0).fullSizeImageUri(); |
| |
| final Bitmap b = makeMiniThumbBitmap(142, 142, list); |
| final int pos = i; |
| final int count = list.getCount(); |
| final Thread currentThread = Thread.currentThread(); |
| mHandler.post(new Runnable() { |
| public void run() { |
| if (mPausing || currentThread != mWorkerThread.realThread()) { |
| if (b != null) { |
| b.recycle(); |
| } |
| return; |
| } |
| |
| ItemInfo info = new ItemInfo(); |
| info.bitmap = b; |
| info.count = count; |
| item.mThumb = info; |
| |
| final GridView grid = GalleryPicker.this.mGridView; |
| final int firstVisible = grid.getFirstVisiblePosition(); |
| |
| // Minor optimization -- only notify if the specified position is visible |
| if ((pos >= firstVisible) && (pos < firstVisible + grid.getChildCount())) { |
| GalleryPickerAdapter.this.notifyDataSetChanged(); |
| } |
| } |
| }); |
| } finally { |
| list.deactivate(); |
| } |
| } |
| } catch (Exception ex) { |
| Log.e(TAG, "got exception generating collage views ", ex); |
| } |
| } |
| }); |
| mWorkerThread.start(); |
| mWorkerThread.toBackground(); |
| } |
| |
| private void addBucketIfNotEmpty(int itemType, String bucketId, int labelId) { |
| if (!isEmptyBucket(Item.convertItemTypeToIncludedMediaType(itemType), bucketId)) { |
| mItems.add(new Item(itemType, bucketId, getResources().getString(labelId))); |
| } |
| } |
| |
| public int getCount() { |
| return mItems.size(); |
| } |
| |
| public Object getItem(int position) { |
| return null; |
| } |
| |
| public long getItemId(int position) { |
| return position; |
| } |
| |
| private String baseTitleForPosition(int position) { |
| return mItems.get(position).mName; |
| } |
| |
| private int getIncludeMediaTypes(int position) { |
| return mItems.get(position).getIncludeMediaTypes(); |
| } |
| |
| public View getView(final int position, View convertView, ViewGroup parent) { |
| View v; |
| |
| if (convertView == null) { |
| LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
| v = vi.inflate(R.layout.gallery_picker_item, null); |
| } else { |
| v = convertView; |
| } |
| |
| TextView titleView = (TextView) v.findViewById(R.id.title); |
| |
| GalleryPickerItem iv = (GalleryPickerItem) v.findViewById(R.id.thumbnail); |
| iv.setOverlay(mItems.get(position).getOverlay()); |
| ItemInfo info = mItems.get(position).mThumb; |
| if (info != null) { |
| iv.setImageBitmap(info.bitmap); |
| String title = baseTitleForPosition(position) + " (" + info.count + ")"; |
| titleView.setText(title); |
| } else { |
| iv.setImageResource(android.R.color.transparent); |
| titleView.setText(baseTitleForPosition(position)); |
| } |
| |
| return v; |
| } |
| }; |
| |
| @Override |
| public void onPause() { |
| super.onPause(); |
| mPausing = true; |
| unregisterReceiver(mReceiver); |
| |
| // free up some ram |
| mAdapter = null; |
| mGridView.setAdapter(null); |
| System.gc(); |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| mPausing = false; |
| |
| mAdapter = new GalleryPickerAdapter(); |
| mGridView.setAdapter(mAdapter); |
| setBackgrounds(getResources()); |
| |
| boolean scanning = ImageManager.isMediaScannerScanning(this); |
| rebake(false, scanning); |
| |
| // install an intent filter to receive SD card related events. |
| IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); |
| intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); |
| intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED); |
| intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED); |
| intentFilter.addAction(Intent.ACTION_MEDIA_EJECT); |
| intentFilter.addDataScheme("file"); |
| |
| registerReceiver(mReceiver, intentFilter); |
| MenuHelper.requestOrientation(this, mPrefs); |
| |
| // Warn the user if space is getting low |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| |
| // Check available space only if we are writable |
| if (ImageManager.hasStorage()) { |
| String storageDirectory = Environment.getExternalStorageDirectory().toString(); |
| StatFs stat = new StatFs(storageDirectory); |
| long remaining = (long)stat.getAvailableBlocks() * (long)stat.getBlockSize(); |
| if (remaining < LOW_STORAGE_THRESHOLD) { |
| |
| mHandler.post(new Runnable() { |
| public void run() { |
| Toast.makeText(GalleryPicker.this.getApplicationContext(), |
| R.string.not_enough_space, 5000).show(); |
| } |
| }); |
| } |
| } |
| } |
| }); |
| t.start(); |
| |
| // If we just have one folder, open it. (Probably never triggered because we always have |
| // At least two folders now.) |
| if (!scanning && mAdapter.mItems.size() <= 1) { |
| android.net.Uri uri = Images.Media.INTERNAL_CONTENT_URI; |
| Intent intent = new Intent(Intent.ACTION_VIEW, uri); |
| startActivity(intent); |
| finish(); |
| return; |
| } |
| } |
| |
| |
| private void setBackgrounds(Resources r) { |
| mFrameGalleryMask = r.getDrawable(R.drawable.frame_gallery_preview_album_mask); |
| |
| mCellOutline = r.getDrawable(android.R.drawable.gallery_thumb); |
| mVideoOverlay = r.getDrawable(R.drawable.ic_gallery_video_overlay); |
| } |
| |
| Handler mHandler = new Handler(); |
| |
| private void placeImage(Bitmap image, Canvas c, Paint paint, int imageWidth, int widthPadding, int imageHeight, int heightPadding, int offsetX, int offsetY, int pos) { |
| int row = pos / 2; |
| int col = pos - (row * 2); |
| |
| int xPos = (col * (imageWidth + widthPadding)) - offsetX; |
| int yPos = (row * (imageHeight + heightPadding)) - offsetY; |
| |
| c.drawBitmap(image, xPos, yPos, paint); |
| } |
| |
| private Bitmap makeMiniThumbBitmap(int width, int height, ImageManager.IImageList images) { |
| int count = images.getCount(); |
| // We draw three different version of the folder image depending on the number of images in the folder. |
| // For a single image, that image draws over the whole folder. |
| // For two or three images, we draw the two most recent photos. |
| // For four or more images, we draw four photos. |
| final int padding = 4; |
| int imageWidth = width; |
| int imageHeight = height; |
| int offsetWidth = 0; |
| int offsetHeight = 0; |
| |
| imageWidth = (imageWidth - padding) / 2; // 2 here because we show two images |
| imageHeight = (imageHeight - padding) / 2; // per row and column |
| |
| final Paint p = new Paint(); |
| final Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); |
| final Canvas c = new Canvas(b); |
| |
| final Matrix m = new Matrix(); |
| |
| // draw the whole canvas as transparent |
| p.setColor(0x00000000); |
| c.drawPaint(p); |
| |
| // draw the mask normally |
| p.setColor(0xFFFFFFFF); |
| mFrameGalleryMask.setBounds(0, 0, width, height); |
| mFrameGalleryMask.draw(c); |
| |
| Paint pdpaint = new Paint(); |
| pdpaint.setXfermode(new android.graphics.PorterDuffXfermode( |
| android.graphics.PorterDuff.Mode.SRC_IN)); |
| |
| pdpaint.setStyle(Paint.Style.FILL); |
| c.drawRect(0, 0, width, height, pdpaint); |
| |
| for (int i = 0; i < 4; i++) { |
| if (mPausing) { |
| return null; |
| } |
| |
| Bitmap temp = null; |
| ImageManager.IImage image = i < count ? images.getImageAt(i) : null; |
| |
| if (image != null) { |
| temp = image.miniThumbBitmap(); |
| } |
| |
| if (temp != null) { |
| if (ImageManager.isVideo(image)) { |
| Bitmap newMap = temp.copy(temp.getConfig(), true); |
| Canvas overlayCanvas = new Canvas(newMap); |
| int overlayWidth = mVideoOverlay.getIntrinsicWidth(); |
| int overlayHeight = mVideoOverlay.getIntrinsicHeight(); |
| int left = (newMap.getWidth() - overlayWidth) / 2; |
| int top = (newMap.getHeight() - overlayHeight) / 2; |
| Rect newBounds = new Rect(left, top, left + overlayWidth, top + overlayHeight); |
| mVideoOverlay.setBounds(newBounds); |
| mVideoOverlay.draw(overlayCanvas); |
| temp.recycle(); |
| temp = newMap; |
| } |
| |
| Bitmap temp2 = ImageLoader.transform(m, temp, imageWidth, imageHeight, true); |
| if (temp2 != temp) |
| temp.recycle(); |
| temp = temp2; |
| } |
| |
| Bitmap thumb = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888); |
| Canvas tempCanvas = new Canvas(thumb); |
| if (temp != null) |
| tempCanvas.drawBitmap(temp, new Matrix(), new Paint()); |
| mCellOutline.setBounds(0, 0, imageWidth, imageHeight); |
| mCellOutline.draw(tempCanvas); |
| |
| placeImage(thumb, c, pdpaint, imageWidth, padding, imageHeight, padding, offsetWidth, offsetHeight, i); |
| |
| thumb.recycle(); |
| |
| if (temp != null) |
| temp.recycle(); |
| } |
| |
| return b; |
| } |
| |
| @Override |
| public boolean onCreateOptionsMenu(Menu menu) { |
| super.onCreateOptionsMenu(menu); |
| |
| MenuHelper.addCaptureMenuItems(menu, this); |
| mFlipItem = MenuHelper.addFlipOrientation(menu, this, mPrefs); |
| |
| menu.add(0, 0, 5, R.string.camerasettings) |
| .setOnMenuItemClickListener(new OnMenuItemClickListener() { |
| public boolean onMenuItemClick(MenuItem item) { |
| Intent preferences = new Intent(); |
| preferences.setClass(GalleryPicker.this, GallerySettings.class); |
| startActivity(preferences); |
| return true; |
| } |
| }) |
| .setAlphabeticShortcut('p') |
| .setIcon(android.R.drawable.ic_menu_preferences); |
| |
| return true; |
| } |
| |
| @Override |
| public boolean onPrepareOptionsMenu(android.view.Menu menu) { |
| MenuHelper.setFlipOrientationEnabled(this, mFlipItem); |
| return true; |
| } |
| |
| private boolean isEmptyBucket(int mediaTypes, String bucketId) { |
| // TODO: Find a more efficient way of calculating this |
| ImageManager.IImageList list = createImageList(mediaTypes, bucketId); |
| try { |
| return list.isEmpty(); |
| } |
| finally { |
| list.deactivate(); |
| } |
| } |
| |
| private ImageManager.IImageList createImageList(int mediaTypes, String bucketId) { |
| return ImageManager.instance().allImages( |
| this, |
| getContentResolver(), |
| ImageManager.DataLocation.ALL, |
| mediaTypes, |
| ImageManager.SORT_DESCENDING, |
| bucketId); |
| } |
| } |