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 存储桶策略时如何避免循环错误?