Android:如何查询存储桶名称列表

Posted

技术标签:

【中文标题】Android:如何查询存储桶名称列表【英文标题】:Android: How to query a list of bucket name 【发布时间】:2012-07-19 05:01:05 【问题描述】:

我只想检索存储桶的名称(相册)。例如。相机、下载等,但不是所有照片中的相机、下载等列表,那么如何为每个存储桶名称分别检索一行?

我在图库应用程序中的意思是,您首先拥有专辑,例如相机。当你点击它时,它会显示相机的所有照片。

我可以使用查询的 Where 子句查询相机胶卷中的照片。但是,如果我只想要每个专辑的名称而不是照片的名称,是否可以查询呢?如果我查询所有照片,每组照片只取一行,那会很耗时。

请帮忙

【问题讨论】:

【参考方案1】:

您可以查询 MediaStore.Images.Media.BUCKET_DISPLAY_NAME。 Peter Knego sent a good example. 这是一个很好的例子,您可以使用 ContentResolver 对象中的 query() 来更新它,而不是使用已弃用的 managedQuery()。

// 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());


【讨论】:

很好,但我只想查询唯一的存储桶显示名称,而不是重复存储桶显示名称的列表。例如。我想要像Camera and Competition这样的专辑。但是对于您的示例代码,它将显示诸如相机、相机、相机、竞赛、竞赛等内容。 是的!我通过将每个元素添加到 HashMap 作为键来解决这个问题。这有点烦人,但它有效。 仍然不能正确解决问题 - 您可以有两个具有相同显示名称和不同照片的唯一文件夹。 BUCKET_IT 是哈希的键 - 而不是显示名称。【参考方案2】:

我有同样的问题,这是我的解决方案(在跟踪画廊源代码之后)获取专辑名称和其中的第一张图片(可以用作此专辑的缩略图):

(请注意,桶重复是通过 groupby 和 order 技术删除的)

    // 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());
    

【讨论】:

如何获取桶中的照片数? 不知道,但我收到了关于 5.0 的重复输入有什么想法吗? @Krunal Shah 我会尝试为每个在 where 参数中过滤 BUCKET_ID 的存储桶运行另一个查询。 在查询所有video专辑的情况下将uri更改为:uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI 此代码不适用于 android pie (android 10) 以上的版本,它在 "1) GROUP BY 1,(2" 关键字中显示语法错误。【参考方案3】:

来了。它对我有用:

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 包含专辑名称

imageUrls Arraylist 包含专辑最后修改图像的路径,您可以将其用作缩略图

【讨论】:

如何获取桶中没有照片? GROUP BY子句的更好方法是:val bucketGroupBy = "1) GROUP BY $ImageColumns.BUCKET_ID, ($ImageColumns.BUCKET_DISPLAY_NAME" 。 Why do we use Group by 1 and Group by 1,2,3 in SQL query?【参考方案4】:

在查询中进行投影,如下所示:

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

【讨论】:

显示名称不是唯一标识符(您可以有两个同名的不同文件夹)- BUCKET_ID 是唯一的。如果您想要一个唯一“文件夹”的列表,则将两个同名视为一个 - 因为两个同名存储桶中有不同的图像。【参考方案5】:

使用以下功能获取视频或图片的相册:

   /*
    *
    *   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( "count(" + MediaStore.Images.ImageColumns._ID + ")"), selection, null, null)

            var count = 0
            if (countCursor != null) 
                countCursor.moveToFirst()
                count = countCursor.getInt(0)
                countCursor.close()
            

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

    


这形成了一个 SQL 语句:

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

更新: 正如@PerracoLabs 指出的那样,此代码需要改进以针对Android Q

【讨论】:

考虑到旧的分组技巧“1) GROUP BY”在 Android Q 中不再适用 我仍在 Q 上对其进行测试。分组查询有效,但 count(*) AS count 无效。 @PerracoLabs 你的意见会很有帮助。 您是否将 Gradle 设置为以 Q 为目标?测试是在模拟器中完成的。当使用 ContentResolver 对 MediaStore 进行查询时,我发现框架在 Where 条件中生成的查询的开头自动包含下一个字符串:(IS_TRASHED=0) AND (IS_PENDING=0)。无论您做什么,这些都会被添加,问题是它们使“1) GROUP ”的括号不平衡,因此会创建无效的语法查询。 除了检查您的代码之外,我还可以看到您正在使用 DATA 字段。不幸的是,这也已被弃用:developer.android.com/reference/android/provider/… 感谢您指出更正。到目前为止,我已经更新了 Android Q 的警告。我会针对目标 Q 进行测试,然后尽快改进代码。

以上是关于Android:如何查询存储桶名称列表的主要内容,如果未能解决你的问题,请参考以下文章

在 bigquery 中使用 RANGE_BUCKET 时如何显示存储桶名称

如何在谷歌存储桶中列出所有上传到存储桶的文件?

CloudFormation 中如何派生 S3 存储桶名称?

使用依赖于存储桶名称的模板设置 S3 存储桶策略时如何避免循环错误?

如何在存储桶名称中使用变量 AWS Cloudformation

如何使用 cloudformation 为 S3 存储桶设置半随机名称