【问题标题】:Android MediaPlayer behavior (event order guarantees)Android MediaPlayer 行为(事件顺序保证)
【发布时间】:2012-06-27 08:22:07
【问题描述】:

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

考虑以下事件顺序:

  1. MediaPlayer 音频流到达其末尾,因此它将一个 OnCompletion 给我的消息
  2. 我的线程:MediaPlayer.pause() 由于用户操作而被调用
  3. 我收到 OnCompletion 调用(太晚了,pause() 已经 上面调用)

这个问题是 MediaPlayer.pause() 只允许在 PAUSED 和 STARTED 状态,但由于第 1 步,MediaPlayer 将 调用 pause() 时已经处于 PlaybackCompleted 状态。我懂了 两种解决方案:

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

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

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

这里的问题是 isPlaying() 仍然会返回 false(因为 docs 也说),因此由于第 3 步,MediaPlayer 仍将启动。

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


更新

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

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

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

还有来自同一页面的另一个引用:

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

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

【问题讨论】:

    标签: java android media-player


    【解决方案1】:

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

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

    但请先尝试一下。它对我来说表现很好,而且我已经对我的垃圾进行了游戏测试。

    【讨论】:

    • 感谢您的确认。几天前,为了确定,我实施了一个解决方法(实际上是一个万无一失的)解决方案,是的。尽管如此,我的结果与您的结果相同,但文档在某些部分确实令人困惑:请参阅我的原始问题帖子以获取报价(我在最后更新了它)。
    • 是的,无论他们添加了多少漂亮的图表和图表,该类的文档都非常混乱。为了让唤醒锁在所有情况下都能正常工作,我差点把该死的头发扯掉。
    • 另一个矛盾的东西是你是否可以在 PlaybackCompleted 状态下调用 pause()。根据文档,您不能(它转移到错误状态),但实际上,您可以。并且考虑到您无法真正同步检查播放是否完成(您只有 onCompletion 回调),您无法知道(没有技巧)您的 pause() 调用是否安全。我向他们发送了一个问题,但目前没有答案:groups.google.com/group/android-platform/browse_thread/thread/…
    • MediaPlayer 有很多问题。它甚至不能给出正确的getCurrentPosition() 一半的时间。这让做节奏游戏变得非常困难。多年来,全班都有大量错误报告,希望您的问题比其他问题得到更多关注。
    • getCurrentPosition() 不适用于 VBR(和一些 CBR)OGG 文件,但它适用于其他格式。题外话,但是:对于 OGG 文件,它甚至可能是故意的疏忽,因为 getCurrentPosition() 在定期使用时似乎返回离散的(〜像量化的)值,并且这些值彼此之间的距离大致相同(例如,如果你使用自己的计数器,每 100 毫秒测量一次,然后得到 0,100,200,300,400,而 getCurrentPosition 返回值如 302,302,302,542。好像为 OGG 生成了某种自己的搜索索引,非常粗糙。
    猜你喜欢
    • 1970-01-01
    • 2020-09-27
    • 2012-07-20
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 2019-08-25
    相关资源
    最近更新 更多