java.lang.IllegalArgumentException Volume external_primary not found in Android 10 devices
Asked Answered
M

3

12

Crash : java.lang.IllegalArgumentException Volume external_primary not found

When querying for tracks from media store, I am getting this crash in some Android 10 devices (Most of them are from Xiaomi Mi A2 Lite, Motorola, HMD Global Nokia).

Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, null);

Should I be passing a different URI for Android 10 devices ?. (However it is working fine in most of the devices )

Stack trace :

Caused by java.lang.IllegalArgumentException: Volume external_primary not found
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
at android.content.ContentProviderProxy.query(ContentProviderProxy.java:423)
at android.content.ContentResolver.query(ContentResolver.java:946)
at android.content.ContentResolver.query(ContentResolver.java:881)
at android.content.ContentResolver.query(ContentResolver.java:837)
at com.example.musicplayer.CursorFactory.getAllSongsCursor(CursorFactory.java:164)

Edit : Based on this issue reported, Suspect it could be an issue with sdcard in those devices with Android 10 OS.

Microfarad answered 27/7, 2020 at 8:3 Comment(1)
SO answer with bounty did not work. And also it isn't right, as it does not get audios inside sdcard and not a elegant way to do it. Have raised a issue with google for the same. issuetracker.google.com/issues/166944434Microfarad
P
6

Post Android 10, API 28, there are some changes when accessing the media content from other sources.

Google mentioned it in this link https://developer.android.com/training/data-storage/shared/media#storage-volume

You can get more information on how to resolve this issue with more information given by google with the below code:

// Add a specific media item.
ContentResolver resolver = getApplicationContext()
        .getContentResolver();

// Find all audio files on the primary external storage device.
// On API <= 28, use VOLUME_EXTERNAL instead.
Uri audioCollection = MediaStore.Audio.Media.getContentUri(
        MediaStore.VOLUME_EXTERNAL_PRIMARY);

// Publish a new song.
ContentValues newSongDetails = new ContentValues();
newSongDetails.put(MediaStore.Audio.Media.DISPLAY_NAME,
        "My Song.mp3");

// Keeps a handle to the new song's URI in case we need to modify it
// later.
Uri myFavoriteSongUri = resolver
        .insert(audioCollection, newSongDetails);

Hope this works for you!

Protoxylem answered 30/7, 2020 at 11:41 Comment(3)
So you meant to say that, in Android 10, API 29, instead of using MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, I have to use MediaStore.Audio.Media.getContentUri( MediaStore.VOLUME_EXTERNAL_PRIMARY) ? , as said this issue is not happening in all the device. Will try out in production and update.Microfarad
The crash is still happening in some devices. However in few cases it worked, and in few it crashed, with the same exception even for MediaStore.Audio.Media.getContentUri( MediaStore.VOLUME_EXTERNAL_PRIMARY) uri.Microfarad
Another observation, MediaStore.Audio.Media.getContentUri( MediaStore.VOLUME_EXTERNAL_PRIMARY) does not load songs that are in SdCard.Microfarad
B
5

Google added a thing called Scoped Storage which changes the File operation a bit. so you should use VOLUME_EXTERNAL/VOLUME_EXTERNAL_PRIMARY instead of EXTERNAL_CONTENT_URI

val uri =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
        } else {
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI
        }

Going with VOLUME_EXTERNAL/VOLUME_EXTERNAL_PRIMARY is the right direction but there is a really rare case that the user stores their audio file on SD card but the phone doesn't recognize it which leads to the crash. This is a device error and there is nothing you can do about it.

From the doc of https://developer.android.com/reference/android/provider/MediaStore#VOLUME_EXTERNAL_PRIMARY

you could use getExternalVolumeNames to check is there any external storage available before making the query.

https://developer.android.com/reference/android/provider/MediaStore#getExternalVolumeNames(android.content.Context)

Blastocoel answered 28/11, 2020 at 9:7 Comment(1)
I used emulator (API31) in Android Studio and sometimes it cannot detect SD card. Not sure if Android Studio problem or not, I need to delete the emulator and create a new one.Inaugurate
O
1

You need to ask read permission for Android Q and above to access files outside of your application scope.

As per documentation mention as below and here is the documention link

If scoped storage is enabled, the collection shows only the photos, videos, and audio files that your app has created. Most developers won't need to use MediaStore.Files to view media files from other apps, but if you have a specific requirement to do so, you can declare the READ_EXTERNAL_STORAGE permission. It's recommended, however, that you use the MediaStore APIs to open files that your app hasn't created.

Here is the common code to ask permission for all version,

Declare the request launcher object

private val requestReadResult = registerForActivityResult(ActivityResultContracts.RequestPermission()) { result ->
    if (result) {
        queryData()
    } else {
        AlertDialog.Builder(this)
                .setMessage(R.string.app_permission_required)
                .setPositiveButton(R.string.exit) { _, _ -> finish() }.setCancelable(false).create().show()
    }
}

Check permission granted or not before query

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
        requestReadResult.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
        return
}
queryData()

Now check for the Android SDK version and as per that initialize your Uri

val uri= if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
    MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
else 
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI

// Here you will getting all the Images from device.
val mediaCursor = contentResolver.query(uri, null, null, null, null)

As per your media requirement change MediaStore.yourmediatype and use it.

Thanks

Opt answered 7/12, 2021 at 10:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.