6

以下错误发生在内部版本号为 RQ1A.201205.003 或更高版本的 Pixel 设备上。
我想知道错误的原因以及如何处理它。
这是错误还是规格更改?

■代码

      ContentResolver resolver = getContentResolver();
      String order = "date ASC limit 100";
      Cursor cursor = resolver.query(
          CallLog.Calls.CONTENT_URI,
          null,
          null,
          null,
          order);

■错误

"Invalid token limit,LINE:142,Method:readExceptionFromParcel Exception:Invalid token limit"

■发生错误的版本号

https://support.google.com/pixelphone/thread/87641266
・RQ1A.201205.003
・RQ1A.201205.008
・RQ1A.201205.011

https://support.google.com/pixelphone/thread/93232095
・RQ1A.210105.002
・RQ1A.210105.003

https://support.google.com/pixelphone/thread/96244000
・RQ1A.210205.004

■如果用下面的代码替换它,就不会发生错误。

buildUpon().appendQueryParameter("limit", "100")

■附加信息 使用官方文档方法执行时,没有出现错误,但该LIMIT子句不起作用(已检索所有记录)。

ContentProvider - 查询

 // Request 20 records starting at row index 30.
 Bundle queryArgs = new Bundle();
 queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 30);
 queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 20);
 
 Cursor cursor = getContentResolver().query(
       contentUri,    // Content Uri is specific to individual content providers.
       projection,    // String[] describing which columns to return.
       queryArgs,     // Query arguments.
       null);         // Cancellation signal.
4

1 回答 1

4

从 Android 11 开始,LIMIT应该OFFSET使用 Bundle 检索

public Cursor query (Uri uri, 
                String[] projection, 
                Bundle queryArgs, 
                CancellationSignal cancellationSignal) 

我使用这样的解决方案,它对我有用:

private fun fetchGalleryImages(
    context: Context,
    orderBy: String,
    orderAscending: Boolean,
    limit: Int = 20,
    offset: Int = 0
): List<MediaItem> {
    val galleryImageUrls = mutableListOf<MediaItem>()
    val collection = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    val projection = arrayOf(
        MediaStore.Files.FileColumns._ID,
        MediaStore.Files.FileColumns.DATA,
        MediaStore.Files.FileColumns.DATE_ADDED,
        MediaStore.Files.FileColumns.MEDIA_TYPE,
        MediaStore.Files.FileColumns.MIME_TYPE,
        MediaStore.Files.FileColumns.TITLE,
        MediaStore.Video.Media.DURATION
    )
    val whereCondition = "${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?"
    val selectionArgs = arrayOf(
        MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(),
        MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString()
    )
    createCursor(
        contentResolver = context.contentResolver,
        collection = collection,
        projection = projection,
        whereCondition = whereCondition,
        selectionArgs = selectionArgs,
        orderBy = orderBy,
        orderAscending = orderAscending,
        limit = limit,
        offset = offset
    )?.use { cursor ->
        while (cursor.moveToNext()) {
            galleryImageUrls.add(
                MediaItem(
                    cursor.getLong(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID)),
                    ContentUris.withAppendedId(collection, cursor.getLong(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID))),
                    cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)),
                    cursor.getStringOrNull(cursor.getColumnIndex(MediaStore.Files.FileColumns.MIME_TYPE)),
                    cursor.getLongOrNull(cursor.getColumnIndex(MediaStore.Video.Media.DURATION))
                )
            )
        }
    }
    return galleryImageUrls
}

private fun createCursor(
    contentResolver: ContentResolver,
    collection: Uri,
    projection: Array<String>,
    whereCondition: String,
    selectionArgs: Array<String>,
    orderBy: String,
    orderAscending: Boolean,
    limit: Int = 20,
    offset: Int = 0
): Cursor? = when {
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
        val selection = createSelectionBundle(whereCondition, selectionArgs, orderBy, orderAscending, limit, offset)
        contentResolver.query(collection, projection, selection, null)
    }
    else -> {
        val orderDirection = if (orderAscending) "ASC" else "DESC"
        var order = when (orderBy) {
            "ALPHABET" -> "${MediaStore.Audio.Media.TITLE}, ${MediaStore.Audio.Media.ARTIST} $orderDirection"
            else -> "${MediaStore.Audio.Media.DATE_ADDED} $orderDirection"
        }
        order += " LIMIT $limit OFFSET $offset"
        contentResolver.query(collection, projection, whereCondition, selectionArgs, order)
    }
}

@RequiresApi(Build.VERSION_CODES.O)
fun createSelectionBundle(
    whereCondition: String,
    selectionArgs: Array<String>,
    orderBy: String,
    orderAscending: Boolean,
    limit: Int = 20,
    offset: Int = 0
): Bundle = Bundle().apply {
    // Limit & Offset
    putInt(ContentResolver.QUERY_ARG_LIMIT, limit)
    putInt(ContentResolver.QUERY_ARG_OFFSET, offset)
    // Sort function
    when (orderBy) {
        "ALPHABET" -> putStringArray(ContentResolver.QUERY_ARG_SORT_COLUMNS, arrayOf(MediaStore.Files.FileColumns.TITLE))
        else -> putStringArray(ContentResolver.QUERY_ARG_SORT_COLUMNS, arrayOf(MediaStore.Files.FileColumns.DATE_ADDED))
    }
    // Sorting direction
    val orderDirection =
        if (orderAscending) ContentResolver.QUERY_SORT_DIRECTION_ASCENDING else ContentResolver.QUERY_SORT_DIRECTION_DESCENDING
    putInt(ContentResolver.QUERY_ARG_SORT_DIRECTION, orderDirection)
    // Selection
    putString(ContentResolver.QUERY_ARG_SQL_SELECTION, whereCondition)
    putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs)
}
于 2021-08-27T11:17:55.707 回答