我自己破解了这个,是的,它是非常类似于 SQL 注入。但是,只要您设法使生成的(生成的)SQL 最终正确,它就可以工作。看看这个例子:
Cursor c_buckets = getContext().getContentResolver().query(baseUri,
new String[]{PhotoContract.ThumbEntry.COLUMN_BUCKET_NAME,
PhotoContract.ThumbEntry.COLUMN_BUCKET_ID + " as _ID"},
"1=1) GROUP BY " + PhotoContract.ThumbEntry.COLUMN_BUCKET_NAME
+ ", " + PhotoContract.ThumbEntry.COLUMN_BUCKET_ID
+ ", ABS(0",
null,
PhotoContract.ThumbEntry.COLUMN_BUCKET_ID
);
query 调用中的selection 字段相当于结果查询的WHERE 子句。 “诀窍”是在selection 末尾的WHERE 子句之后添加GROUP BY 子句。 WHERE 子句用括号括起来,所以诀窍是在WHERE 子句(这里只是1=1)之后添加一个右括号,方法是将1=1) 添加到selection。然后你可以插入你的GROUP BY 子句。然而,由于 Android 会期望所有这些都是选择,所以它会在最后添加一个右括号!为了克服这个问题,您需要在末尾添加一些需要右括号的内容。我发现简单地将ABS(0 添加到分组中很方便。这对分组没有影响,它解决了语法问题,导致有效的SQL:
SELECT images.bucket_display_name, images.bucket_id as _ID FROM images WHERE (1=1) GROUP BY images.bucket_display_name, images.bucket_id, ABS(0) ORDER BY images.bucket_id
请注意,我正在使用别名添加所需的“_id”列,而不会干扰分组。
Android Q (API 29) 更新:
为了在 API 29 (Android Q) 上工作,列名不能再以表名作为前缀。如,images.bucket_display_name 应该只是 bucket_display_name。