This tutorial describes a way to associate just certain images with the Gallery View. Recall from the Tutorial:Camera_and_Gallery_Demo that the Gallery in that example displayed all of the images stored on the phone. In this example, we populate the Gallery with just those images created by the Demo App.
Camera images are saved in Android's MediaStore.Images.Media.EXTERNAL_CONTENT_URI and the thumbnails are saved in MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI. The thumbnails record contains a reference to the corresponding image in their IMAGE_ID field.
Therefore, given the thumbnail, you can retrieve the corresponding image as is most likely done by the built-in Camera and Gallery applications. However, the image's record does not contain a usable reference to the corresponding thumbnails. There is a field named MINI_THUMB_MAGIC in the image record. But this field is apparently overwritten by Android's built-in Gallery or Slideshow App. Therefore, we use the image's PICASA_ID field to store the ID of the image's corresponding mini thumbnail.
The ACTION_IMAGE_CAPTURE activity returns a bitmap to the onActivityResult() method.
In the displayGallery() method, we retrieve only those images taken by our App.
In the ImageAdapter.getView() method:
In the onClickItemListener() method:
To implement this modification, we need a new constant defintion:
private static final String OUR_TITLE = "DemoImage";
and we need to replace the call to insertImage() in the onActivityResult() method with a call to a new method, saveImageAndThumbnails(Bitmap):
// Revised code in onActivityResult() if (b.containsKey(MediaStore.EXTRA_OUTPUT)) { // large image? showToast(this,"Large image"); // Should have to do nothing for big images -- should already saved in MediaStore ... but saveImageAndThumbnails(bm); Log.i(TAG, "This is a large image: "); } else { showToast(this,"Small image"); saveImageAndThumbnails(bm); Log.i(TAG, "This is a small image: "); } break;
The saveImageAndThumbnails() method, implements the first part of the above algorithm:
private void saveImageAndThumbnails(Bitmap bm) { // Save the image. This also saves a micro and mini thumbnail String sUri = MediaStore.Images.Media.insertImage(getContentResolver(), bm, OUR_TITLE, TAG); // Now update the mini Thumbnail record with the image's ID int imgId = Integer.parseInt(sUri.substring(sUri.lastIndexOf("/")+1)); // Strip off the Id num Uri thumbUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI; // Thumbnail provider // Query for the mini thumbnail for the image just saved. There should be just 1. // See the comments on showGallery() for an explanation of managedQuery() String[] projection = { MediaStore.Images.ImageColumns._ID, // The columns we want MediaStore.Images.Thumbnails.IMAGE_ID, MediaStore.Images.Thumbnails.KIND }; String selection = MediaStore.Images.Thumbnails.KIND + " = " + MediaStore.Images.Thumbnails.MINI_KIND + " AND " + MediaStore.Images.Thumbnails.IMAGE_ID + " = " + imgId; Cursor c = this.managedQuery(thumbUri, projection, selection, null, null); // Should return just 1 c.moveToFirst(); Log.i(TAG, "Save Cursor = " + c.getCount()); int thumbId = c.getInt(c.getColumnIndexOrThrow(MediaStore.Images.ImageColumns._ID)); // Thumbnail ID // Update the image's entry with the Thumbnail's ID ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(MediaStore.Images.ImageColumns.PICASA_ID, thumbId); cr.update(Uri.parse(sUri), values, "", null); }
In the previous version of displayGallery() we queried for mini thumbnails and passed them along to ImageAdapter. This time we query for the images themselves and pass them along to ImageAdapter:
private void displayGallery() { Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; // Where images are stored displaySdCard(); String[] projection = { // The columns we want MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.TITLE, MediaStore.Images.ImageColumns.PICASA_ID }; // PICASA_ID is thumbnail's ID String selection = MediaStore.Images.ImageColumns.TITLE + " = /"" + OUR_TITLE + "/""; // Our images mCursor = this.managedQuery(uri, projection, selection, null, null); // Create an ImageAdapter with the Cursor and assign it to the Gallery if (mCursor != null) { mCursor.moveToFirst(); ImageAdapter adapter = new ImageAdapter(mCursor, this); Log.i(TAG, "displayGallery(), adapter = " + adapter.getCount()); mGallery.setAdapter(adapter); mGallery.setOnItemClickListener(this); } else showToast(this, "Gallery is empty."); }
In the previous version of getView() the Adapter was passed thumbnails, which were assigned to the appropriate ImageView in the gallery. In this version, we are passed images. We retrieve the associated thumbnail ID from the PICASA_ID field, retrieve the thumbnail's Uri, and set the ImageView:
public View getView(int position, View convertView, ViewGroup parent) { Log.i(TAG, "Get view = " + position); ImageView i = new ImageView(mContext); mCursor.requery(); if (convertView == null) { mCursor.moveToPosition(position); // Protocol: PICASA_ID is set to _ID of the mini thumbnail when the image is saved. int thumbId = mCursor.getInt(mCursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.PICASA_ID)); Uri thumbUri = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, ""+thumbId); Log.i(TAG, "Thumbnail Uri = " + thumbUri.toString()); try { i.setImageURI(thumbUri); i.setScaleType(ImageView.ScaleType.FIT_XY); i.setLayoutParams(new Gallery.LayoutParams(136, 136)); i.setBackgroundResource(mGalleryItemBackground); } catch (Exception e) { Log.i(TAG, "Exception " + e.getStackTrace()); } } return i; }
In the previous version we were passing thumbnails to the Cursor and had to retrieve the corresponding image, using the IMAGE_ID field in the Cursor. Now we are passing images to the Cursor, so we retrieve the image's ID from the Cursor:
mCursor.moveToPosition(position); //long id = mCursor.getLong(mCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID)); long id = mCursor.getLong(mCursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns._ID));
The source code is here: Media:camera-gallery2.zip. Download the zip file. Unzip it and then use it to create a new Android project.