Get list of photo galleries on Android

I'm looking for: A list of the existing photo gallery names (hopefully their top thumbnail as well) The contents of the gallery (I can then load thumbnails and full size as needed)

How would I go about getting a list of the "Galleries" (don't know if that's the proper term in android for the groupings of images visible in the Gallery app...) and their contents? I need access to the gallery in it's structure without using the existing gallery display (I'm creating a totally new one, not an over layer to the photo requestor etc.)

I assume MediaStore.Images is where I need to be but I don't see anything that will give me the groupings...


Solution 1:

Groupings are defined by MediaStore.Images.Media.BUCKET_DISPLAY_NAME. Here is the sample code to list the images and log their bucket name and date_taken:

// which image properties are we querying
String[] projection = new String[] {
        MediaStore.Images.Media._ID,
        MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
        MediaStore.Images.Media.DATE_TAKEN
};

// content:// style URI for the "primary" external storage volume
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

// Make the query.
Cursor cur = managedQuery(images,
        projection, // Which columns to return
        null,       // Which rows to return (all rows)
        null,       // Selection arguments (none)
        null        // Ordering
        );

Log.i("ListingImages"," query count=" + cur.getCount());

if (cur.moveToFirst()) {
    String bucket;
    String date;
    int bucketColumn = cur.getColumnIndex(
        MediaStore.Images.Media.BUCKET_DISPLAY_NAME);

    int dateColumn = cur.getColumnIndex(
        MediaStore.Images.Media.DATE_TAKEN);

    do {
        // Get the field values
        bucket = cur.getString(bucketColumn);
        date = cur.getString(dateColumn);

        // Do something with the values.
        Log.i("ListingImages", " bucket=" + bucket 
               + "  date_taken=" + date);
    } while (cur.moveToNext());

}

Solution 2:

/**
 * Getting All Images Path
 * 
 * @param activity
 * @return ArrayList with images Path
 */
public static ArrayList<String> getAllShownImagesPath(Activity activity) {
    Uri uri;
    Cursor cursor;
    int column_index_data, column_index_folder_name;
    ArrayList<String> listOfAllImages = new ArrayList<String>();
    String absolutePathOfImage = null;
    uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

    String[] projection = { MediaColumns.DATA,
            MediaStore.Images.Media.BUCKET_DISPLAY_NAME };

    cursor = activity.getContentResolver().query(uri, projection, null,
            null, null);

    column_index_data = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
    column_index_folder_name = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
    while (cursor.moveToNext()) {
        absolutePathOfImage = cursor.getString(column_index_data);

        listOfAllImages.add(absolutePathOfImage);
    }
    return listOfAllImages;
}

Solution 3:

Here is the full solution in few simple steps:

The next few steps will guid you how to create a Vector that will hold the albums found on a given device. Every Album will hold a preview image as well an inner Vector that will hold all the images of the Album.

  1. Create an object that will hold the images once extracted from storage. We are going to call it PhoneAlbum. This is how it's going to look:

    public class PhoneAlbum {
    
        private int id;
        private String name;
        private String coverUri;
        private Vector<PhonePhoto> albumPhotos;
    
        public int getId() {
            return id;
        }
    
        public void setId( int id ) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName( String name ) {
            this.name = name;
        }
    
        public String getCoverUri() {
            return coverUri;
        }
    
        public void setCoverUri( String albumCoverUri ) {
            this.coverUri = albumCoverUri;
        }
    
        public Vector< PhonePhoto > getAlbumPhotos() {
            if ( albumPhotos == null ) {
                albumPhotos = new Vector<>();
            }
            return albumPhotos;
        }
    
        public void setAlbumPhotos( Vector< PhonePhoto > albumPhotos ) {
            this.albumPhotos = albumPhotos;
        }
    }
    
  2. Create an object that will hold the images within the album called: PhonePhoto

    public class PhonePhoto {
    
        private int id;
        private String albumName;
        private String photoUri;
    
        public int getId() {
            return id;
        }
    
        public void setId( int id ) {
            this.id = id;
        }
    
        public String getAlbumName() {
            return albumName;
        }
    
        public void setAlbumName( String name ) {
            this.albumName = name;
        }
    
        public String getPhotoUri() {
            return photoUri;
        }
    
        public void setPhotoUri( String photoUri ) {
            this.photoUri = photoUri;
        }
    }
    
  3. Create an interface to handle the extracted images upon completion. We are going to call it OnPhoneImagesObtained. Here it is:

    public interface OnPhoneImagesObtained {
    
        void onComplete( Vector<PhoneAlbum> albums );
        void onError();
    
    }
    
  4. Create a new class: DeviceImageManager

    public class DeviceImageManager {
    
    }
    
  5. Once you created DeviceImageManager, add the following method:

    public static void getPhoneAlbums( Context context , OnPhoneImagesObtained listener ){
        // Creating vectors to hold the final albums objects and albums names
        Vector< PhoneAlbum > phoneAlbums = new Vector<>();
        Vector< String > albumsNames = new Vector<>();
    
        // which image properties are we querying
        String[] projection = new String[] {
                MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
                MediaStore.Images.Media.DATA,
                MediaStore.Images.Media._ID
        };
    
        // content: style URI for the "primary" external storage volume
        Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    
        // Make the query.
        Cursor cur = context.getContentResolver().query(images,
                projection, // Which columns to return
                null,       // Which rows to return (all rows)
                null,       // Selection arguments (none)
                null        // Ordering
        );
    
        if ( cur != null && cur.getCount() > 0 ) {
            Log.i("DeviceImageManager"," query count=" + cur.getCount());
    
            if (cur.moveToFirst()) {
                String bucketName;
                String data;
                String imageId;
                int bucketNameColumn = cur.getColumnIndex(
                    MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
    
                int imageUriColumn = cur.getColumnIndex(
                    MediaStore.Images.Media.DATA);
    
                int imageIdColumn = cur.getColumnIndex(
                    MediaStore.Images.Media._ID );
    
                do {
                    // Get the field values
                    bucketName = cur.getString( bucketNameColumn );
                    data = cur.getString( imageUriColumn );
                    imageId = cur.getString( imageIdColumn );
    
                    // Adding a new PhonePhoto object to phonePhotos vector
                    PhonePhoto phonePhoto = new PhonePhoto();
                    phonePhoto.setAlbumName( bucketName );
                    phonePhoto.setPhotoUri( data );
                    phonePhoto.setId( Integer.valueOf( imageId ) );
    
                    if ( albumsNames.contains( bucketName ) ) {
                        for ( PhoneAlbum album : phoneAlbums ) {
                            if ( album.getName().equals( bucketName ) ) {
                                album.getAlbumPhotos().add( phonePhoto );
                                Log.i( "DeviceImageManager", "A photo was added to album => " + bucketName );
                                break;
                            }
                        }
                    } else {
                        PhoneAlbum album = new PhoneAlbum();
                        Log.i( "DeviceImageManager", "A new album was created => " + bucketName );
                        album.setId( phonePhoto.getId() );
                        album.setName( bucketName );
                        album.setCoverUri( phonePhoto.getPhotoUri() );
                        album.getAlbumPhotos().add( phonePhoto );
                        Log.i( "DeviceImageManager", "A photo was added to album => " + bucketName );
    
                        phoneAlbums.add( album );
                        albumsNames.add( bucketName );
                    }
    
                } while (cur.moveToNext());
            }
    
            cur.close();
            listener.onComplete( phoneAlbums );
        } else {
            listener.onError();
        }
    }
    
  6. Now all you have left is to render the images to screen. In my case I like to use Picasso. Here is how I do it:

        Picasso.with( getActivity() )
                    .load( "file:" + mPhoneAlbums.get( i ).getCoverUri() )
                    .centerCrop()
                    .fit()
                    .placeholder( R.drawable.temp_image )
                    .into( mAlbumPreview );
    
  7. Don't forget to add a permission to read external storage in your manifest:

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    

That's it. You are good to go! Good luck!