【问题标题】:Unable to play audio file after application reset - java.io.IOException: setDataSource failed.: status=0x80000000应用程序重置后无法播放音频文件 - java.io.IOException: setDataSource failed.: status=0x80000000
【发布时间】:2021-09-28 21:06:21
【问题描述】:

我正在创建允许向用户播放音频文件、创建多个播放列表和交叉淡入淡出每首歌曲/播放列表等的应用程序。

到目前为止一切正常,我可以选择歌曲文件,并通过将它们加载到 MediaPlayer 中正确播放它们

但问题是如果我重新启动应用程序。神奇的是,以前正确读取的所有 Uri 都不再可访问?

这就是我加载歌曲的方式(删除了某些部分 - 视图等)

val intent = new Intent()
        .setData(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI)
        .putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
        .setAction(Intent.ACTION_OPEN_DOCUMENT )
        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        .addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
        .addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
startActivityForResult.launch(intent);
    private final ActivityResultLauncher<Intent> startActivityForResult = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == RESULT_OK) {
                    val data = result.getData();
                    if (data.getData() != null) {
                        val uri = data.getData();
                        songOutOfUri(uri);
                    } else if (data.getClipData() != null && data.getClipData().getItemCount() > 0) {
                        val clipData = data.getClipData();
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            val uri = clipData.getItemAt(i).getUri();
                            songOutOfUri(uri);
                        }
                    }
                    ///...view update
                }
            }
    );

    private void songOutOfUri(Uri uri) {
        val file = new File(uri.getPath());
        val song = Song.builder()
                .filename(file.getName())
                .fileUri(uri.toString())
                .filePath(file.getPath())
                .build();
        song.save();
        playlistService.addSongToPlaylist(playlist, song);
    }

这种意图的结果基本上是一些歌曲添加到我的播放列表中,它们包含文件名(为了更好地显示)文件路径和 fileUri。所有都使用https://github.com/ImangazalievM/ReActiveAndroid 持久化到数据库中(因此 uri 到字符串)

然后我尝试播放文件:

///...
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(getApplicationContext(), Uri.parse(currentSong.getFileUri()));
mediaPlayer.prepare();
mediaPlayer.seekTo(position);
mediaPlayer.start();

它适用于多首歌曲,但只有在我杀死 /reset 应用程序之前 如果我再次重新打开应用程序,我会收到媒体播放器错误:

W/System.err: java.io.IOException: setDataSource failed.: status=0x80000000
W/System.err:     at android.media.MediaPlayer.nativeSetDataSource(Native Method)
        at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1243)
W/System.err:     at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1230)
        at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1147)
        at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1072)

持久歌曲示例:

{
"id":20,
"filename":"05 Mindi Abair - Lucy's.mp3", 
"fileUri":"content://com.android.externalstorage.documents/document/primary%3AMusic%2Fsongs%2F05%20Mindi%20Abair%20-%20Lucy's.mp3", 
"filePath":"/document/primary:Music/songs/05 Mindi Abair - Lucy's.mp3", 
"currentPosition":0
}

也尝试将文件作为文件读取并使用 fileDescriptor 进行播放,但即使在第一次尝试时也得到了 FileNotFound(没有重置)

在使用 uri 重置之前尝试播放它可以使用文件描述符,但不会

File file = new File(currentSong.getFilePath()); //also tried with Uri.parse(song.getFileUri)
FileInputStream is = new FileInputStream(file);
mediaPlayer.setDataSource(is.getFD());
//throws java.io.FileNotFoundException: /document/primary:Music/songs/05 Mindi Abair - Lucy's.mp3: open failed: ENOENT (No such file or directory)

Manifest 当然有读取存储的权限

【问题讨论】:

    标签: android audio android-mediaplayer


    【解决方案1】:

    我能够通过遵循官方文档https://developer.android.com/training/data-storage/shared/documents-files 中的试验来解决问题 然后在github上查看一些示例

    对于任何在打开文件时遇到类似问题的人

    开始选择文件:

    Intent intent = new Intent(ACTION_OPEN_DOCUMENT)
          .setData(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI)
          .setFlags(FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
          .putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    startActivityForSelectedFiles.launch(intent);
    

    startActivityForSelectedFiles 保持不变

    那么关键的部分 1 是当我们收到 URI 时,我们必须正确地用权限标记它。

    requireActivity()
        .getApplicationContext()
        .getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
    
    //rest of uri handling 
    val file = new File(uri.getPath());
    val song = Song.builder()...
    
    

    然后每当我们想用 uri 访问我们的文件时:

    ...
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor());
    val fileDescriptor = getContentResolver().openFileDescriptor(uri, "r");
    mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor());
    mediaPlayer.prepare();
    mediaPlayer.seekTo(position);
    mediaPlayer.start();
    

    现在每次都有效

    【讨论】:

      猜你喜欢
      • 2017-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-17
      • 2011-05-24
      相关资源
      最近更新 更多