#android #audio #mediastore
#Android #Аудио #mediastore
Вопрос:
Я не нашел никакой официальной документации, объясняющей, как сохранить аудиофайл на внешнем хранилище с помощью MediaStore API. В API 29 все работает. В API 28 — я получаю эту ошибку:
E/JavaBinder: *** Uncaught remote exception! (Exceptions are not yet supported across processes.)
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:2036)
at com.android.providers.media.MediaProvider.insertFile(MediaProvider.java:2188)
at com.android.providers.media.MediaProvider.insertInternal(MediaProvider.java:2592)
at com.android.providers.media.MediaProvider.insert(MediaProvider.java:1872)
at android.content.ContentProvider$Transport.insert(ContentProvider.java:266)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:152)
at android.os.Binder.execTransact(Binder.java:731)
Это код, который я использую (когда я вызываю «вставить», я получаю нулевой Uri):
//@RequiresApi(VERSION_CODES.Q)
@SuppressLint("InlinedApi")
private fun export(name: String, path: String) {
val resolver = applicationContext.contentResolver
val audioCollection = if (VERSION.SDK_INT >= VERSION_CODES.Q) {
MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
}
val newAudioFileDetails = ContentValues().apply {
put(MediaStore.Audio.Media.DISPLAY_NAME, name)
put(MediaStore.Audio.Media.DATA, "data")
put(MediaStore.Audio.Media.IS_PENDING, 1)
}
val recordingUri = resolver.insert(audioCollection, newAudioFileDetails)
Log.d(TAG, "recording Uri: ${recordingUri.toString()}")
recordingUri?.let { recordingUri ->
resolver.openFileDescriptor(recordingUri, "w")?.use {
val bytesCopied = File(path).inputStream().copyTo(FileOutputStream(it.fileDescriptor))
Log.d("TAG", "bytes copied: $bytesCopied")
}
newAudioFileDetails.let {
it.clear()
it.put(MediaStore.Audio.Media.IS_PENDING, 0)
resolver.update(recordingUri, it, null, null)
}
}
}
Редактировать
Я также пытался с этим, но при вставке я всегда получаю нулевой Uri:
val newAudioFileDetails = ContentValues().apply {
put(MediaStore.Audio.Media.DISPLAY_NAME, name)
put(MediaStore.Audio.Media.IS_PENDING, 1)
if (VERSION.SDK_INT < VERSION_CODES.Q) {
val audioDir = File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MUSIC), "MyNewAlbumName")
val audioPath = File(audioDir, "$name.mp3").absolutePath
put(MediaStore.Audio.AudioColumns.DATA, audioPath)
}
Комментарии:
1. У вас есть
StringIndexOutOfBoundsException
.2.
......Media.DATA, "data"
? Что это должно быть? Вы должны указать путь.3. какой путь я должен указать?
4. Исключение StringIndexOutOfBoundsException генерируется классом ContentResolver: я просто получаю в ответ нулевой Uri
5. Путь, по которому должен быть сохранен ваш файл. Полный путь к каталогу. Или полный путь к файлу. Попробуйте оба.