Android MediaPlayer卡在prepare()中

Android MediaPlayer卡在prepare()中,android,media-player,Android,Media Player,媒体播放器(MP)卡在prepare()方法上,我面临严重问题。 我的应用程序在AsyncTask中运行prepare(),以避免阻塞用户界面,因为源代码来自web。用户可以随时单击几个“播放”按钮,因此我在同步方法中添加了prepare(),以更好地控制MP的状态。我的应用程序还调用一个release()onPause来释放已使用的资源 问题是,我注意到,如果在准备过程中调用了release(),prepare()将永远不会返回,因此我被困在一个同步方法中。最糟糕的是,AsyncTask线程处

媒体播放器(MP)卡在
prepare()
方法上,我面临严重问题。 我的应用程序在
AsyncTask
中运行
prepare()
,以避免阻塞用户界面,因为源代码来自web。用户可以随时单击几个“播放”按钮,因此我在同步方法中添加了
prepare()
,以更好地控制MP的状态。我的应用程序还调用一个
release()
onPause来释放已使用的资源

问题是,我注意到,如果在准备过程中调用了
release()
prepare()
将永远不会返回,因此我被困在一个同步方法中。最糟糕的是,
AsyncTask
线程处于死锁状态,每次用户在该状态下单击play,另一个线程都会被浪费,因为它一直在等待获取拥有永不返回的
prepare()
的监视器。很快,我所有的
AsyncTasks
线程都被浪费了,由于我大量使用它们,我的应用程序停止工作


所以我的问题是:有人知道如何克服这个问题吗?我正在认真考虑用MediaPlayer重做所有工作,但我需要事先知道处理类似情况的最佳方法。

您应该使用
prepareAsync()
。而且你不需要仅仅为了准备而使用
AsyncTask

使用
asyntask
prepareAsync()
的问题在于它不会自动将
MediaPlayer的状态切换为prepared。你会认为是的,但出于某种原因,它不是。我被同样的问题困扰了几天,直到有人建议我实现
OnPreparedListener
,并使用它来使用我的
MediaPlayer

添加它非常简单

首先,在您的类中实现侦听器:(我将其用于服务,因此您的侦听器看起来会略有不同。)

接下来,在play/prepare语句中,使用
prepareAsync
,并设置侦听器

mp.prepareAsync();
mp.setOnPreparedListener(this);
接下来,添加
onPrepared
方法并添加起始代码:

public void onPrepared(MediaPlayer mediaplayer) {
        // We now have buffered enough to be able to play
        mp.start();
    }

这应该可以解决问题。

感谢所有的答案,但我没有像前面的答案中提到的那样使用prepareAsync()来解决这个问题。我认为,如果有一种同步的准备方法可用,那么应该有一种方法使其正确工作

修复方法虽然不优雅,但很简单:避免在prepare()中调用release()。尽管Media Player文档中的状态图表示可以在任何状态下调用release(),但实验证明,在prepare()中调用它(可能处于“Preparing”状态)将挂起应用程序。所以我添加了一个检查,看看MP是否处于这种状态,如果是,我现在避免调用release()。我需要在代码中添加一个布尔值来检查这一点,因为MP中没有isPreparing()方法


我相信这不应该发生,这是Android本身的一个缺陷。从注释中可以看出,文档中存在一个矛盾:它说可以在任何状态下调用release(),但也说在准备状态下调用任何状态更改命令都会产生未定义的结果。希望这能帮助其他人。

我的媒体播放器因为使用了不安全的URL(HTTP而不是HTTPS)而陷入了准备阶段

我必须在android清单中添加以下内容

<application
    ...
    android:usesCleartextTraffic="true"
    ...
</application>

我想到了这一点,但我不确定它是否能解决眼前的问题。MediaPlayer文档说,“需要注意的是,准备状态是一个瞬态,当MediaPlayer对象处于准备状态时,调用任何具有副作用的方法的行为都是未定义的。”因此问题仍然存在,我将在“准备”状态下调用release(),结果是未定义的。我怀疑在我的synchronous prepare()中,MediaPlayer会转移到这个“准备”状态,这会导致我收到的错误。根据图表和状态表,您可以从任何状态调用
release()
。试试看。我认为您正面临与多线程相关的bug。排除多个线程应该可以“修复”它。它确实说我可以随时调用release(),但即使如此,如果我在prepare()中调用它,我仍然面临着被卡住的问题。这不应该发生,而且是Android IMO中的一个bug。不,我是说,即使文档说我可以随时调用
release()
,我也面临着被困在
prepare()
中的原始问题。我认为使用
prepareAsync()
,这不是一个坏主意,但我确实相信应该有一种方法可以让它在
prepare()
中正常工作。这是正确的解决方案。您标记为答案的解决方案只是围绕MediaPlayer已经提供给您的功能进行工作。
<application
    ...
    android:usesCleartextTraffic="true"
    ...
</application>