Android: How to query a list of bucket name

2019-03-18 17:50发布

问题:

I want to retrieve only the name of the bucket (Albums). E.g. Camera, Download etc but not a list of Camera, Download etc from all the the photos so how do I retrieve one row each for each bucket name?

What I mean like in Gallery Application, you have albums first e.g. Camera. When you clicked on it, it show all the photos of the camera.

I can query the photos in a Camera Roll with the Where clause of the query. But what if I wanted only the name of each of the albums' name and not the photos, is it possible to query that? If I query all the photos and take only one row per set of photos, then it will be time consuming.

Please Help

回答1:

I have the same problem and here is my solution (after tracing gallery source code) to get album name and the first image in it (can use as thumbnail for this album):

(Note that bucket repeat is removed by groupby & order technique)

    // which image properties are we querying
    String[] PROJECTION_BUCKET = {
            ImageColumns.BUCKET_ID,
            ImageColumns.BUCKET_DISPLAY_NAME,
            ImageColumns.DATE_TAKEN,
            ImageColumns.DATA};
    // We want to order the albums by reverse chronological order. We abuse the
    // "WHERE" parameter to insert a "GROUP BY" clause into the SQL statement.
    // The template for "WHERE" parameter is like:
    //    SELECT ... FROM ... WHERE (%s)
    // and we make it look like:
    //    SELECT ... FROM ... WHERE (1) GROUP BY 1,(2)
    // The "(1)" means true. The "1,(2)" means the first two columns specified
    // after SELECT. Note that because there is a ")" in the template, we use
    // "(2" to match it.
    String BUCKET_GROUP_BY =
            "1) GROUP BY 1,(2";
    String BUCKET_ORDER_BY = "MAX(datetaken) DESC";

    // Get the base URI for the People table in the Contacts content provider.
    Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

    Cursor cur = getContentResolver().query(
            images, PROJECTION_BUCKET, BUCKET_GROUP_BY, null, BUCKET_ORDER_BY);

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

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

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

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

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


回答2:

Here it is. it works for me:

Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    String[] projection = new String[]{   
            MediaStore.Images.Media.BUCKET_ID,
            MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
            MediaStore.Images.Media.DATE_TAKEN,
            MediaStore.Images.Media.DATA
    };

    String BUCKET_ORDER_BY = MediaStore.Images.Media.DATE_MODIFIED + " DESC";
    String BUCKET_GROUP_BY = "1) GROUP BY 1,(2";
    Cursor imagecursor = managedQuery(images,
            projection, // Which columns to return
            BUCKET_GROUP_BY,       // Which rows to return (all rows)
            null,       // Selection arguments (none)
            BUCKET_ORDER_BY        // Ordering
            );

    this.imageUrls = new ArrayList<String>();
    this.imageBuckets  = new ArrayList<String>();
    for (int i = 0; i < imagecursor.getCount(); i++)
    {
        imagecursor.moveToPosition(i);
        int bucketColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
        String bucketDisplayName = imagecursor.getString(bucketColumnIndex);
        imageBuckets.add(bucketDisplayName);
        int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
        imageUrls.add(imagecursor.getString(dataColumnIndex));

    }

imageBuckets Arraylist is containing album names

imageUrls Arraylist is containing path of last modifided image of album you can use it as thumbnail



回答3:

Use following function to get albums of Video or Images :

   /*
    *
    *   Author : @nieldeokar
    *   mediaType could be one of
    *
    *   public static final int MEDIA_TYPE_IMAGE = 1;
    *
    *   public static final int MEDIA_TYPE_VIDEO = 3;
    *
    *   from android.provider.MediaStore class
    *
    */
fun getAlbumList(mediaType: Int, contentResolver: ContentResolver) {
    val countColumnName = "count"
    var contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    if (mediaType == MEDIA_TYPE_VIDEO) {
        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
    }

    val projection = arrayOf(ImageColumns.BUCKET_ID, ImageColumns.BUCKET_DISPLAY_NAME, ImageColumns.DATE_TAKEN, ImageColumns.DATA)
    val bucketGroupBy = "1) GROUP BY ${ImageColumns.BUCKET_ID}, (${ImageColumns.BUCKET_DISPLAY_NAME}"
    val bucketOrderBy = MediaStore.Images.Media.DATE_MODIFIED + " DESC"

    val cursor = contentResolver.query(contentUri, projection, bucketGroupBy, null, bucketOrderBy)


    if (cursor != null) {
        while (cursor.moveToNext()) {
            val bucketId = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.BUCKET_ID))
            val name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME))
            val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)) // Thumb image path

            val selection = MediaStore.Images.Media.BUCKET_ID + "='" + bucketId + "'"

            val countCursor = contentResolver.query(contentUri, arrayOf("$countColumnName(*) AS $countColumnName"), selection, null, null)

            var count = 0
            if (countCursor != null) {
                countCursor.moveToFirst()
                count = countCursor.getInt(countCursor.getColumnIndexOrThrow(countColumnName))
                countCursor.close()
            }

            Log.d("AlbumScanner", "bucketId : $bucketId | name : $name | count : $count | path : $path")
        }
        cursor.close()

    }

}

This forms a SQL Statement as :

SELECT bucket_id, bucket_display_name, datetaken, _data FROM images WHERE (1) GROUP BY bucket_id,(bucket_display_name) ORDER BY date_modified DESC


回答4:

You can query MediaStore.Images.Media.BUCKET_DISPLAY_NAME for it. Peter Knego sent a good example. It's a good example and you can update it using query() from a ContentResolver object rather than managedQuery() that is deprecated.

// 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
};

// Get the base URI for the People table in the Contacts content provider.
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

// Make the query.
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(images,
        projection, // Which columns to return
        "",         // Which rows to return (all rows)
        null,       // Selection arguments (none)
        ""          // 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());

}


回答5:

Do projection in query as below:

String bucketProjection[] = {"Distinct "+ MediaStore.Images.Media.BUCKET_DISPLAY_NAME};