2

假设有两个线程:我的线程和 MediaPlayer 线程(通过 looper 向我发送消息)。我的游戏线程对用户输入做出反应:如果用户暂停游戏,我也会调用 MediaPlayer.pause()。

考虑以下事件顺序:

  1. MediaPlayer 音频流到达终点,因此它将 OnCompletion 消息排入队列给我
  2. 我的线程:MediaPlayer.pause() 由于用户操作而被调用
  3. 我收到 OnCompletion 调用(为时已晚,上面已经调用了 pause())

这样做的问题是 MediaPlayer.pause() 只允许在 PAUSED 和 STARTED 状态下,但是由于第 1 步,当调用 pause() 时 MediaPlayer 已经处于 PlaybackCompleted 状态。我看到两个解决方案:

  1. 捕捉异常
  2. 在调用 pause() 之前询问 MediaPlayer.isPlaying()

但是第二种方案在以下场景中存在问题:

  1. 游戏开始,MediaPlayer.start() 被调用,但媒体播放器状态 尚未开始
  2. 用户离开游戏,调用代码: if(isPlaying()) pause();
  3. MediaPlayer 进入 STARTED 状态(现在 isPlaying 将返回 true,但为时已晚)

这里的问题是 isPlaying() 仍将返回 false (正如文档所说),因此 MediaPlayer 仍将由于第 3 步而启动。

是否有正确的解决方案并在这两种情况下都避免异常?(或者我上面的思路有什么错误吗?)


更新

对 Geobits 的回答做出反应(我在这里这样做是因为我会引用 Android 文档):

是的,我也在做本地播放,和你一样测试了很多,一切看起来都很好。但是文档有点自相矛盾。第一部分(这没关系):

调用 start() 为暂停的 MediaPlayer 对象恢复播放,恢复的播放位置与暂停的位置相同。当对 start() 的调用返回时,暂停的 MediaPlayer 对象将返回 Started 状态

来自同一页面的另一句话:

播放可以暂停和停止,当前播放位置可以调整。可以通过 pause() 暂停播放。当对 pause() 的调用返回时,MediaPlayer 对象进入 Paused 状态。请注意,从 Started 状态到 Paused 状态的转换(反之亦然)在播放器引擎中异步发生。在对 isPlaying() 的调用中更新状态可能需要一些时间,在流式内容的情况下可能需要几秒钟。

后者表示,当启动暂停播放器时,状态更改可能需要时间(“反之亦然”)。到目前为止一切都很好,因为它仅适用于内部播放器引擎,但随后出现了疯狂的部分:“在调用 isPlaying() 时更新状态可能需要一些时间”。这意味着 isPlaying()没有返回 OBSERVABLE 状态,而是取决于内部状态。这令人困惑。

4

1 回答 1

2

我用MediaPlayer做了一些应用程序,if(isPlaying()) pause();每次使用都没有不良影响。不过,这是当地媒体的情况。如果您正在流式传输,则延迟实际上可能会导致第二种问题。

试一试,看看你能不能打破它。如果你不能,那就没什么好担心的。如果可以的话,你总是可以解决它。当你打电话时设置一个布尔值start(),排队暂停,我敢肯定还有其他我没有想到的方法。

但是先试试看。它对我来说表现良好,而且我已经对我的垃圾进行了游戏测试。

于 2012-06-27T00:03:42.487 回答