I was trying to get buckets having audio files using MediaStore
. This is working fine on Android 10 API 29 but not working previous Android versions. I've attached a screenshot of working example on Android 10 API 29.
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
logcat.
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)
Code:
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);
}
}
...
I did it my self now. First retrieved all audio files, then separated audio URIs. From audio URIs, I've got Folder Names. I'm posting my solution here so maybe someone else can get benefit from it.