Replacement for “GROUP BY” in ContentResolver query in Android Q ( Android 10, API 29 changes)

 ̄綄美尐妖づ 提交于 2020-05-16 03:59:46

问题


I'm upgrading some legacy to target Android Q, and of course this code stop working:

       String[] PROJECTION_BUCKET = {MediaStore.Images.ImageColumns.BUCKET_ID,
            MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
            MediaStore.Images.ImageColumns.DATE_TAKEN,
            MediaStore.Images.ImageColumns.DATA,
            "COUNT(" + MediaStore.Images.ImageColumns._ID + ") AS COUNT",
            MediaStore.Files.FileColumns.MEDIA_TYPE,
            MediaStore.MediaColumns._ID};

        String BUCKET_GROUP_BY = " 1) and " + BUCKET_WHERE.toString() + " GROUP BY 1,(2";

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

android.database.sqlite.SQLiteException: near "GROUP": syntax error (code 1 SQLITE_ERROR[1])

Here it supposed to obtain list of images with album name, date, count of pictures - one image for each album, so we can create album picker screen without querying all pictures and loop through it to create albums.

Is it possible to group query results with contentResolver since SQL queries stoped work?

(I know that ImageColumns.DATA and "COUNT() AS COUNT" are deprecated too, but this is a question about GROUP BY)

(There is a way to query albums and separately query photo, to obtain photo uri for album cover, but i want to avoid overheads)


回答1:


Unfortunately the Group By will no longer work in Android 10. And as you already found out, aggregated functions such as the COUNT one, will neither work.

The solution is what are actually trying to avoid, to query, iterate, and get metrics.

To get you started you can use the next snipped, which will resolve the buckets (albums), and the amount of records in each one.

I haven't added code to resolve the thumbnails, but is easy. You must perform a query for each bucket Id from all the Album instances, and use the image from the first record.

public final class AlbumQuery
{
    @NonNull
    public static HashMap<String, AlbumQuery.Album> get(@NonNull final Context context)
    {
        final HashMap<String, AlbumQuery.Album> output     = new HashMap<>();
        final Uri                               contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

        final String[] projection = {MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.Images.Media.BUCKET_ID};

        try (final Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null))
        {
            if ((cursor != null) && (cursor.moveToFirst() == true))
            {
                final int columnBucketName = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
                final int columnBucketId   = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_ID);

                do
                {
                    final String bucketId   = cursor.getString(columnBucketId);
                    final String bucketName = cursor.getString(columnBucketName);

                    if (output.containsKey(bucketId) == false)
                    {
                        final int              count = AlbumQuery.getCount(context, contentUri, bucketId);
                        final AlbumQuery.Album album = new AlbumQuery.Album(bucketId, bucketName, count);
                        output.put(bucketId, album);
                    }

                } while (cursor.moveToNext());
            }
        }

        return output;
    }

    private static int getCount(@NonNull final Context context, @NonNull final Uri contentUri, @NonNull final String bucketId)
    {
        try (final Cursor cursor = context.getContentResolver().query(contentUri,
                null, MediaStore.Images.Media.BUCKET_ID + "=?", new String[]{bucketId}, null))
        {
            return ((cursor == null) || (cursor.moveToFirst() == false)) ? 0 : cursor.getCount();
        }
    }

    public static final class Album
    {
        @NonNull
        public final String buckedId;
        @NonNull
        public final String bucketName;
        public final int    count;

        Album(@NonNull final String bucketId, @NonNull final String bucketName, final int count)
        {
            this.buckedId = bucketId;
            this.bucketName = bucketName;
            this.count = count;
        }
    }
}


来源:https://stackoverflow.com/questions/60623594/replacement-for-group-by-in-contentresolver-query-in-android-q-android-10-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!