在准备状态下重置MediaPlayer是否安全?

8
我正在使用MediaPlayer编写音频播放器,允许用户跳过实际的曲目。 跳过请求可能会在任何时候发生,包括在调用MediaPlayer.prepareAsync和即将到来的onPrepared回调之间。文档说:
“需要注意的是,准备状态是一个瞬态状态,而在MediaPlayer对象处于准备状态时调用具有副作用的任何方法的行为都是未定义的。”
这是否包括reset甚至是release的调用?如果是这样,那么我要么必须等待onPrepared回调才能重用MediaPlayer,要么在不想等待并在onPrepared回调上释放过时的MediaPlayer时分配全新的MediaPlayer,对吗?
3个回答

5

我曾经制作过一个流媒体播放器,在准备状态时遇到了困难。最糟糕的是,有些流媒体在下载(缓冲)数据时会永远卡在prepare()方法中,而从未调用onBufferUpdate方法。调用release()方法也没有任何效果。所以,我的做法是在15秒后从另一个线程上调用reset()方法来重置卡住的MediaPlayer,尽管文档中不建议这样做。这导致它抛出异常并进入错误状态。在捕获异常后,我调用了release()方法。这似乎解决了问题。希望对某人有用。


3

我的看法是要遵循文档中的建议。我发现在不同设备上使用播放器时存在几个问题(有些设备完全不能重复使用相同的播放器)。

我认为一个好的选择是分配两个播放器,并在用户跳过曲目时在它们之间切换,然后等待原始播放器准备好并安全地重置它。


2
我曾经在某个地方读到过,MediaPlayer实例相当耗费资源,我们不应该依赖于超过两个。我已经使用了两个实例:一个用于播放实际的音乐,另一个用于准备(和播放)下一个音乐。因此,如果MediaPlayer.release始终有效,那么我可以确保我始终只有两个MediaPlayer实例。 - Simon
这没问题,有两个实例,你可以等待处于准备状态的一个实例转换为已准备好状态后再释放它,而另一个实例则播放下一首曲子。 - Lucas S.

-1

我在使用MP时遇到了一个问题,它在准备状态下停留时间过长(流式传输),我试图使用reset()来停止它。这导致MP挂起,从而使我的整个应用程序冻结。似乎没有办法在准备状态下停止MP。我考虑使用prepare()包装在线程中,而不是使用prepareAsync()。然后我就可以杀死那个线程了。目前我是这样做的:

        try {
            mp.setDataSource(new String());
        } catch (Exception e) {
            e.printStackTrace();
            android.util.Log.d(TAG,"actionCancel(): mp.setDataSource() exception");
            mp.reset();
        }

它对我有效。


在你的代码中,如果捕获到异常,那是因为你试图给你的玩家设置新的数据。然后你重置了你的玩家... 但最终你没有将数据设置给玩家。 - Jeje Doudou
你可能没有读我的帖子,所以你没明白诀窍。我不需要设置任何数据源,我只需要在准备阶段停止/重置MP。只有在捕获异常后,我才能安全地使用重置。 - Stan
文档中提到:“需要注意的是,准备状态是一种短暂的状态,在MediaPlayer对象处于准备状态时调用任何具有副作用的方法的行为是未定义的。”使用这种方式是否会产生任何副作用? - wukong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接