Java IllegalArgumentException:无效的列不同存储桶\u显示\u名称
我正在检索不同文件夹列表,每个文件夹中都有视频文件,每个文件夹中都有视频文件,这在安卓p及以下版本的设备上运行良好,但当我在安卓Q设备上运行时,应用程序崩溃。 我如何让它在运行安卓Q的设备上工作 java.lang.IllegalArgumentException:无效列 bucket\u显示\u名称 日志:Java IllegalArgumentException:无效的列不同存储桶\u显示\u名称,java,android,android-studio,mediastore,Java,Android,Android Studio,Mediastore,我正在检索不同文件夹列表,每个文件夹中都有视频文件,每个文件夹中都有视频文件,这在安卓p及以下版本的设备上运行良好,但当我在安卓Q设备上运行时,应用程序崩溃。 我如何让它在运行安卓Q的设备上工作 java.lang.IllegalArgumentException:无效列 bucket\u显示\u名称 日志: java.lang.IllegalArgumentException: Invalid column DISTINCT bucket_display_name at and
java.lang.IllegalArgumentException: Invalid column DISTINCT bucket_display_name
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:423)
at android.content.ContentResolver.query(ContentResolver.java:944)
at android.content.ContentResolver.query(ContentResolver.java:880)
at android.content.ContentResolver.query(ContentResolver.java:836)
at com.aisar.mediaplayer.fragments.VideoFolderFragment$MediaQuery.getAllVideo(VideoFolderFragment.java:364)
at com.aisar.mediaplayer.fragments.VideoFolderFragment$VideosLoader.loadVideos(VideoFolderFragment.java:434)
at com.aisar.mediaplayer.fragments.VideoFolderFragment$VideosLoader.access$1100(VideoFolderFragment.java:413)
at com.aisar.mediaplayer.fragments.VideoFolderFragment$5.run(VideoFolderFragment.java:189)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
我的代码:
public class MediaQuery {
private Context context;
private int count = 0;
private Cursor cursor;
List<ModelVideoFolder> videoItems;
public MediaQuery(Context context) {
this.context = context;
}
public List<ModelVideoFolder> getAllVideo(String query) {
String selection = null;
String[] projection = {
"DISTINCT " + MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.BUCKET_ID
};
cursor = context.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
null,
query);
videoItems = new ArrayList<>();
ModelVideoFolder videoItem;
while (cursor.moveToNext()) {
videoItem = new ModelVideoFolder(
"" + cursor.getString(1),
"" + cursor.getString(0),
"",
"",
"" + getVideosCount(cursor.getString(1))
);
videoItems.add(videoItem);
}
return videoItems;
}
public int getVideosCount(String BUCKET_ID) {
int count = 0;
String selection = null;
String[] projection = {
MediaStore.Video.Media.BUCKET_ID,
};
Cursor cursor = getActivity().getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
null,
null);
while (cursor.moveToNext()) {
if (BUCKET_ID.equals(cursor.getString(0))) {
//add only those videos that are in selected/chosen folder
count++;
}
}
return count;
}
}
公共类MediaQuery{
私人语境;
私有整数计数=0;
私有游标;
列出视频项目;
公共媒体查询(上下文){
this.context=上下文;
}
公共列表getAllVideo(字符串查询){
字符串选择=null;
字符串[]投影={
“独特”+MediaStore.Video.Media.BUCKET\u显示\u名称,
MediaStore.Video.Media.BUCKET\u ID
};
cursor=context.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL\u CONTENT\u URI,
投影,
选择,
无效的
查询);
videoItems=新的ArrayList();
模型视频文件夹视频项目;
while(cursor.moveToNext()){
videoItem=新型号VideoFolder(
“”+cursor.getString(1),
“”+cursor.getString(0),
"",
"",
“”+GetVideoScont(cursor.getString(1))
);
添加(videoItem);
}
归还录像带物品;
}
public int getvideoscont(字符串BUCKET\u ID){
整数计数=0;
字符串选择=null;
字符串[]投影={
MediaStore.Video.Media.BUCKET_ID,
};
游标游标=getActivity().getContentResolver().query(
MediaStore.Video.Media.EXTERNAL\u CONTENT\u URI,
投影,
选择,
无效的
无效);
while(cursor.moveToNext()){
if(BUCKET_ID.equals(cursor.getString(0))){
//仅添加选定/选定文件夹中的视频
计数++;
}
}
返回计数;
}
}
DISTINCT关键字实际上属于SELECT
语句,而不是列。例如选择不同的国家/地区,从CountryStable中选择名称
。因此,将DISTINCT
添加到列投影是一种黑客行为,它在以前的Android版本中随机工作,并且可能由于某些更改而在Android 10中停止工作。由于ContentResolver
不允许原始查询,因此只需过滤代码中的唯一文件夹即可。G通过使用HashSet
这是由于Android Q中的限制
在Android Q中,投影必须只包含有效的列名,而不包含其他语句。无法再在投影中嵌入任何类型的SQL语句
因此,投影(如“DISTINCT”+YourColumName)或甚至尝试将列别名(如“ExistingColumnName”作为另一个名称)都将始终失败
解决方法是执行多个查询(游标)以获取所需的度量,并使用结果或进行构造
请参阅下一个问题链接,其中说明了此行为与预期一致,因为它是Q中改进的存储安全模型的一部分:
对于您的具体问题,解决方案如下:
public static class MediaQuery
{
@NonNull
public static HashMap<String, ModelVideoFolder> get(@NonNull final Context context)
{
final HashMap<String, ModelVideoFolder> output = new HashMap<>();
final Uri contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
final String[] projection = {MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.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.Video.Media.BUCKET_DISPLAY_NAME);
final int columnBucketId = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_ID);
do
{
final String bucketName = cursor.getString(columnBucketName);
final String bucketId = cursor.getString(columnBucketId);
if (output.containsKey(bucketId) == false)
{
final int count = MediaQuery.getCount(context, contentUri, bucketId);
final ModelVideoFolder item = new ModelVideoFolder(
bucketName, bucketId, null, null, count);
output.put(bucketId, item);
}
} 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.Video.Media.BUCKET_ID + "=?", new String[]{bucketId}, null))
{
return ((cursor == null) || (cursor.moveToFirst() == false)) ? 0 : cursor.getCount();
}
}
}
公共静态类MediaQuery
{
@非空
公共静态HashMap get(@NonNull final Context)
{
最终HashMap输出=新HashMap();
最终Uri contentUri=MediaStore.Video.Media.EXTERNAL\u CONTENT\u Uri;
最终字符串[]投影={MediaStore.Video.Media.BUCKET\显示\名称,
MediaStore.Video.Media.BUCKET\u ID};
try(最终游标=context.getContentResolver().query(contentUri,
投影,空,空,空)
{
if((cursor!=null)&&(cursor.moveToFirst()=true))
{
final int columnBucketName=cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET\u DISPLAY\u NAME);
final int columnBucketId=cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_ID);
做
{
最终字符串bucketName=cursor.getString(columnBucketName);
最终字符串bucketId=cursor.getString(columnBucketId);
if(output.containsKey(bucketId)==false)
{
final int count=MediaQuery.getCount(上下文、contentUri、bucketId);
最终ModelVideoFolder项目=新ModelVideoFolder(
bucketName,bucketId,null,