Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java IllegalArgumentException:无效的列不同存储桶\u显示\u名称_Java_Android_Android Studio_Mediastore - Fatal编程技术网

Java IllegalArgumentException:无效的列不同存储桶\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

我正在检索不同文件夹列表,每个文件夹中都有视频文件,每个文件夹中都有视频文件,这在安卓p及以下版本的设备上运行良好,但当我在安卓Q设备上运行时,应用程序崩溃。 我如何让它在运行安卓Q的设备上工作

java.lang.IllegalArgumentException:无效列 bucket\u显示\u名称

日志:

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中改进的存储安全模型的一部分:

对于您的具体问题,解决方案如下:

  • 首先查询光标以获取所有视频所在的BUCKET_ID值列表。在所选内容中,您可以使用MediaStore.files.FileColumns.MEDIA\u TYPE=MediaStore.files.FileColumns.MEDIA\u TYPE\u video进行筛选,以仅针对视频文件

  • 使用检索到的游标,迭代所有BUCKET_ID值,对每个BUCKET执行单独的查询,并检索视频记录,从中可以解析计数。在迭代过程中,跟踪每个BUCKET_ID并跳过任何已查询的BUCKET_ID。不要忘记也执行相同的媒体类型过滤器选择,以避免查询可能位于同一存储桶中的无视频文件

  • 请尝试您的问题代码中的下一个代码片段,我尚未对其进行测试,但您可能会了解如何继续:

    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,