【问题标题】:android.database.sqlite.SQLiteException: no such column: bucket_display_nameandroid.database.sqlite.SQLiteException:没有这样的列:bucket_display_name
【发布时间】:2020-01-22 14:41:59
【问题描述】:

我试图使用MediaStore 获取包含音频文件的存储桶。这在 Android 10 API 29 上运行良好,但不适用于以前的 Android 版本。我附上了 Android 10 API 29 上工作示例的屏幕截图。

原因:android.database.sqlite.SQLiteException:没有这样的列: bucket_display_name(代码 1 SQLITE_ERROR):,编译时:SELECT bucket_display_name, bucket_id FROM audio ORDER BY date_added ASC

日志猫。

Caused by: android.database.sqlite.SQLiteException: no such column: bucket_display_name (code 1 SQLITE_ERROR): , while compiling: SELECT bucket_display_name, bucket_id FROM audio ORDER BY date_added ASC
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:179)
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
        at android.content.ContentProviderProxy.query(ContentProviderNative.java:418)
        at android.content.ContentResolver.query(ContentResolver.java:802)
        at android.content.ContentResolver.query(ContentResolver.java:752)
        at android.content.ContentResolver.query(ContentResolver.java:710)
        at com.aisar.mediaplayer.fragments.AudioFolderFragment$AsyncVideoFolderLoader.doInBackground(AudioFolderFragment.java:148)
        at com.aisar.mediaplayer.fragments.AudioFolderFragment$AsyncVideoFolderLoader.doInBackground(AudioFolderFragment.java:130)
        at android.os.AsyncTask$2.call(AsyncTask.java:333)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
        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:764) 

代码:

class AsyncVideoFolderLoader extends AsyncTask<String, String, List<ModelAudioFolder>> {

    private String sortBy;

    public AsyncVideoFolderLoader(String sortBy) {
        this.sortBy = sortBy;
    }

    @Override
    protected List<ModelAudioFolder> doInBackground(String... strings) {
        List<ModelAudioFolder> videoItems = new ArrayList<>();
        videoItems.clear();

        final HashMap<String, ModelAudioFolder> output = new HashMap<>();
        final Uri contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;

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

        try (final Cursor cursor = getActivity().getContentResolver().query(
                contentUri,
                projection,
                null,
                null,
                "" + sortBy)) {
            if ((cursor != null) && (cursor.moveToFirst())) {
                final int columnBucketName = cursor.getColumnIndex(MediaStore.Audio.Media.BUCKET_DISPLAY_NAME);
                final int columnBucketId = cursor.getColumnIndex(MediaStore.Audio.Media.BUCKET_ID);


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

                    if (!output.containsKey(bucketId)) {
                        final int count = getCount(contentUri, bucketId);

                        final ModelAudioFolder item = new ModelAudioFolder(
                                "" + bucketId,
                                "" + bucketName,
                                "",
                                "" + getPath(bucketId),
                                "" + count
                        );

                        output.put(bucketId, item);
                        videoItems.add(item);

                    }

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

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

    private String getPath(String BUCKET_ID) {
        String path = "";
        String selection = null;
        String[] projection = {
                MediaStore.Audio.Media.DATA,
                MediaStore.Audio.Media.BUCKET_ID
        };
        Cursor cursor = getActivity().getContentResolver().query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                projection,
                selection,
                null,
                null);
        while (cursor.moveToNext()) {
            if (BUCKET_ID.equals(cursor.getString(1))) {
                //add only those videos that are in selected/chosen folder
                path = cursor.getString(0);
            }
        }
        return path;
    }

    @Override
    protected void onPostExecute(List<ModelAudioFolder> audioFolderList) {
        super.onPostExecute(audioFolderList);

        if (audioFolderList.size() <= 0) {
            noFoldersRl.setVisibility(View.VISIBLE);
            foldersRl.setVisibility(View.GONE);
        } else {
            noFoldersRl.setVisibility(View.GONE);
            foldersRl.setVisibility(View.VISIBLE);
        }

        Log.d("FoldersSize", "onPostExecute: " + audioFolderList.size());

        adapterAudioFolder = new AdapterAudioFolder(getActivity(), audioFolderList, dashboardActivity);
        foldersRv.setAdapter(adapterAudioFolder);
    }
}

...

【问题讨论】:

  • 贴出表'audio'的创建/结构代码
  • 这是使用“MediaStore”类加载音频存储桶的完整类。如果我仍然理解错误,请告诉我
  • 我可以得到文件夹名称。我发布了解决方案here

标签: java android android-sqlite mediastore sqliteexception


【解决方案1】:

异常原因是BUCKET_DISPLAY_NAME。它是在 API 29 中添加的。在此之前,我们将 DISPLAY_NAME 用于 API 28 及以下版本。请参考文档BUCKET_DISPLAY_NAME

对于解决方案,您可以根据当前 API 级别编写条件。对于获取文件夹名称,您可以使用RELATIVE_PATH

【讨论】:

  • 有什么方法可以让存储桶在 API 29 以下有音频文件?
  • 我想在他们发布相同的支持 sdk 之前没有办法
  • 和 'RELATIVE_PATH' 也被添加到 API 29 中。我认为那没有办法
【解决方案2】:

在 API 版本中

也就是说,在 29 以下版本中获取 audios 的 BUCKET_DISPLAY_NAME 的解决方案是解析 MediaStore.Files.FileColumns.DATA。该字段在 29 中已弃用,但在以前的版本中仍然有效。

该字段包含实际路径 + 文件名,由于 BUCKET_DISPLAY_NAME 实际上是文件所在的实际 文件夹名称,您需要做的是删除文件名,并且然后从路径中最后找到的反斜杠开始获取子字符串。

【讨论】:

    【解决方案3】:

    我现在自己做了。首先检索所有音频文件,然后分离音频 URI。从音频 URI 中,我得到了文件夹名称。我在这里发布我的解决方案,以便其他人可以从中受益。

    class AsyncVideoFolderLoader extends AsyncTask<String, String, List<ModelAudioFolder>> {
    
        private Cursor cursor;
        List<ModelAudioTe> audioList;
    
        private String sortBy;
    
        public AsyncVideoFolderLoader(String sortBy) {
            this.sortBy = sortBy;
        }
    
        @Override
        protected List<ModelAudioFolder> doInBackground(String... strings) {
    
            String selection = null;
            String[] projection;
            projection = new String[]{
                    MediaStore.Audio.Media._ID,
                    MediaStore.Audio.Media.TITLE,
                    MediaStore.Audio.Media.ARTIST,
                    MediaStore.Audio.Media.DURATION,
                    MediaStore.Audio.Media.ALBUM,
                    MediaStore.Audio.Media.DATA,
                    MediaStore.Audio.Media.SIZE,
                    MediaStore.Audio.Media.ALBUM_ID
            };
            cursor = getActivity().getContentResolver().query(
                    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                    projection,
                    selection,
                    null,
                    null);
            audioList = new ArrayList<>();
            ModelAudioTe modelAudio;
            while (cursor.moveToNext()) {
    
    
                modelAudio = new ModelAudioTe(
                        "" + cursor.getString(0),
                        "" + cursor.getString(1),
                        "" + cursor.getString(2),
                        "" + cursor.getString(3),
                        "" + cursor.getString(4),
                        "" + cursor.getString(5),
                        "" + cursor.getString(6),
                        "" + cursor.getString(7));
                audioList.add(modelAudio);
    
            }
    
    
            //creating audio paths/uris list
            ArrayList<String> pathsList = new ArrayList<>();
            pathsList.clear();
            for (int i = 0; i < audioList.size(); i++) {
                String folderName = new File(audioList.get(i).getDATA()).getParentFile().getName();
                String folderId = new File(audioList.get(i).getDATA()).getParentFile().getParent();
                pathsList.add(folderId + "/" + folderName);
            }
    
    
            //generating folder names from audio paths/uris
            List<ModelAudioFolder> folderList = new ArrayList<>();
            folderList.clear();
            for (int i = 0; i < audioList.size(); i++) {
    
                String folderName = new File(audioList.get(i).getDATA()).getParentFile().getName();
                String folderId = new File(audioList.get(i).getDATA()).getParentFile().getParent();
                int count = Collections.frequency(pathsList, folderId + "/" + folderName);
    
                String folderRoot;
                String folderRoot1 = "";
                if (audioList.get(i).getDATA().contains("emulated")) {
                    folderRoot = "emulated";
                } else {
                    folderRoot = "storage";
                }
    
                if (i > 0) {
                    if (audioList.get(i - 1).getDATA().contains("emulated")) {
                        folderRoot1 = "emulated";
                    } else {
                        folderRoot1 = "storage";
                    }
                }
                if (i == 0) {
    
                    ModelAudioFolder model = new ModelAudioFolder("" + folderId + "/" + folderName, "" + folderName, "", "" + folderId + "/" + folderName, "" + count);
                    folderList.add(model);
                    Log.d("The_Tag1", "onCreate: " + folderName + " " + folderRoot + " " + folderId + "/" + folderName + " " + count);
    
                } else if (
                        folderName.equals(new File(audioList.get(i - 1).getDATA()).getParentFile().getName())
                                &&
                                folderRoot.equals(folderRoot1)
    
                ) {
                    //exclude
                } else {
                    ModelAudioFolder model = new ModelAudioFolder("" + folderId + "/" + folderName, "" + folderName, "", "" + folderId + "/" + folderName, "" + count);
                    folderList.add(model);
    
                    Log.d("The_Tag1", "onCreate: " + folderName + " " + folderRoot + " " + folderId + "/" + folderName + " " + " " + count);
    
                }
    
            }
    
    
            return folderList;
        }
    
        @Override
        protected void onPostExecute(List<ModelAudioFolder> audioFolderList) {
            super.onPostExecute(audioFolderList);
    
            Log.d("ModelAudioFolder_Size", "Count:" + audioFolderList.size());
    
            try {
                if (audioFolderList.size() <= 0) {
                    noFoldersRl.setVisibility(View.VISIBLE);
                    foldersRl.setVisibility(View.GONE);
                } else {
                    noFoldersRl.setVisibility(View.GONE);
                    foldersRl.setVisibility(View.VISIBLE);
                }
    
                Log.d("FoldersSize", "onPostExecute: " + audioFolderList.size());
    
                adapterAudioFolder = new AdapterAudioFolder(getActivity(), audioFolderList, dashboardActivity);
                foldersRv.setAdapter(adapterAudioFolder);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-25
      • 2013-10-03
      • 2016-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      相关资源
      最近更新 更多