AudioSystem在交叉淡化2个MediaPlayer对象时随机关闭

Kev*_*vin 5 java android android-mediaplayer

我该从哪里开始?!我花了很多时间试图调试这个,但没有用.我打了一个deadend,真的很感激一些帮助.

我的场景:我正在尝试为Android制作一个能够交叉淡化每首歌曲的媒体播放器.我创建了2个MediaPlayer对象(playerA和playerB),其中playerA是播放"第一首歌"的播放器.理想的情况是,如果用户通过MediaPlayerController点击下一个按钮或者歌曲距离结束还有10秒 - 播放器A开始逐渐淡出OUT,同时播放器B加载一首歌曲,开始播放它,并淡化音量 - 给出你的交叉渐变效果.

虽然我已经让这个工作,但我必须说,我有随机的失败.我将失败定义为:下一首歌曲(通过"其他"播放器播放)你将听不到任何声音.我已经检查了失败/安静播放器的实际状态,同时它表现出这种行为,并且.isPlayer()= true和playerA.getDuration() - playerA.getCurrentPosition()正在计算,所以MediaPlayer认为它实际上正在播放 - 但是你又一次听不到任何声音.

我已经尝试了一百万种不同的方式,但是再一次,不能随意"破解"它.我尝试做"重复代码"以使其淡出和进入的方式是通过一个单独的线程使用位于服务启动方法中的UI句柄,我尝试使用TimerTask,我尝试使用postDelayed处理程序有许多不同的延迟(handler_crossfadeA.postDelayed(runnable_crossfadeA,500);)

一些技术细节:我通过一个扩展MediaPlayer的单例创建了每个playerA和playerB(其中包括一百万个其他内容)因此我只获得了1个实例,我的主要活动绑定到播放声音的MusicService,我正在使用Android L/5 API,我正在测试Nexus 5

所以我通过极大地减少我的代码来跟踪它,这导致问题(再次,它是随机的 - 但通常发生在5首歌曲中,但我确实得到一些代码可以持续多达20首歌曲):给定播放器A应用程序首次启动时开始,然后将下一首歌曲转换为playerB,然后播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放器播放设 最终我能够通过在playerB开始停止播放器A(消除所有音量输入和输出调整等)后500ms设置postDelayed处理程序来轻松地重现这一点.我甚至尝试将我的stop()和reset()代码移动到不同的方法,包括我的crossfade方法,在我的playSong()方法中,在onPrepare()方法中.

总结一下:

  • 如果我在MediaPlaye的onPrepared()中设置了playerB的setDataSource - > start()之后删除任何"睡眠"(或等待),我可以正常工作.
  • 虽然这打破了它:playerA正在播放 - >点击下一首歌曲按钮 - > playerB设置数据源 - > call prepare()(prepareAsync()具有相同的行为) - > onPrepared()调用start() - >睡眠500ms或更长时间 - > stop()&reset()(或者只是重置()播放器A.再次,它重置播放器播放器B播放后播放器已经播放了.我知道我的情况似乎有些奇怪,但我觉得Android应该没有问题处理这个. /sf/ask/1722262671/是相关的,但绝不是同样的问题.

虽然我有大量的代码不适合这篇文章,但在将其拆除以进行故障排除之后,这就是我通常所拥有的(如果我遗漏了相关内容,请提前道歉):

服务启动方法的一部分:

handler_crossfadeA = new Handler(); guiHandler= new Handler(Looper.getMainLooper());

为每个玩家在服务启动时调用的init()方法:

    playerA.setAudioSessionId(11);
    playerA.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
    playerA.setAudioStreamType(AudioManager.STREAM_MUSIC);
    playerA.setOnPreparedListener(this);
    playerA.setOnCompletionListener(this);
    playerA.setOnErrorListener(this);
Run Code Online (Sandbox Code Playgroud)

playSong()方法的一部分

try{ playerA.setDataSource(getApplicationContext(), trackUri); } catch(Exception e){ } try{ playerA.prepare(); } catch (IllegalStateException e) { e.printStackTrace();} catch (IOException e) { }

onPrepared()方法的一部分:

playerA.start(); //or call playerB.start if its not the next player call crossfade method

交叉淡入淡出方法的一部分,每个玩家的不同变化:

handler_crossfadeA_iteration=0; runnable_crossfadeA = new Runnable(){ @Override public void run() { playerA.stop(); playerA.reset(); } }; handler_crossfadeA.postDelayed(runnable_crossfadeA,500); //500ms isnt ideal but i got it to still break this way


我认为最相关的错误是导致这种情况:

  • AudioSystem - ioConfigChanged()关闭未知输出!
  • 我在Android c ++代码中查找了这个错误,但找不到任何有用的线索

以下相关错误:

  • audio_hw_primary - out_set_parameters:输入:usecae(3:compress-offload-playback)kvpairs:exiting = 1
  • offload_visualizer - 线程退出
  • audio_hw_primary - disable_audio_route:reset和update mixer path:compress-offload-playback
  • audio_hw_primary - offload_thread_loop:compress handle为null

至少我发帖,所以我希望我可以与他人分享我的经验,并在一个地方获得所有这些信息.

完整的错误截图: 在此输入图像描述