Search code examples
androidandroid-contentresolverandroid-10.0android-storage

How do insert file with content resolver in Android?


I'm trying to insert audio file to shared storage in Android. I'm getting error on api 29(emulator).

Error :

java.lang.IllegalArgumentException: Primary directory (invalid) not allowed for content://media/external_primary/audio/media; allowed directories are [Alarms, Music, Notifications, Podcasts, Ringtones]

My Code is:

...
Uri collection = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 
                ? MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
                : MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);

values = new ContentValues();
values.put(MediaStore.Audio.Media.DISPLAY_NAME, targetFileName);
values.put(MediaStore.Audio.Media.RELATIVE_PATH, targetFileDirPath);
values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/mpeg");
values.put(MediaStore.Audio.Media.IS_PENDING, 1);

resolver = getContentResolver();
uri = resolver.insert(collection, values); // error throws from here
outputStream = uri != null ? resolver.openOutputStream(uri) : null;
...

What is the cause of this error and how can I solve this problem?


Solution

  • Apparently, MediaStore.Audio.Media.getContentUri() does not return a directly-usable Uri, at least on Android 10+. It points to an abstract location for "audio", but you cannot write content directly to that Uri. Instead, you need to use RELATIVE_PATH to specify one of the supported collections (Alarms, Music, Notifications, Podcasts, Ringtones), and then any path that you want inside of there.

    Note, though, that RELATIVE_PATH itself is new to Android 10. For Android 9 and older devices, I recommend just writing to the filesystem directly.