MediaPlayer
更换dataSource
播放器时,Android
出现问题。根据MediaPlayer
(http://developer.android.com/reference/android/media/MediaPlayer.html)的规范,reset
更改时我必须对播放器进行操作dataSource
。这可以正常工作,但是一旦channelChanged
快速连续两次调用该方法,就会MediaPlayer.reset
冻结UI。我分析了代码,如下所示:
public void channelChanged(String streamingUrl)
{
long m1 = System.currentTimeMillis();
mMediaPlayer.reset();
long m2 = System.currentTimeMillis();
try
{
mMediaPlayer.setDataSource(streamingUrl);
}
catch (IOException e)
{
e.printStackTrace();
}
long m3 = System.currentTimeMillis();
mMediaPlayer.prepareAsync();
long m4 = System.currentTimeMillis();
Log.d("MEDIAPLAYER", "reset: " + (m2 - m1));
Log.d("MEDIAPLAYER", "setDataSource: " + (m3 - m2));
Log.d("MEDIAPLAYER", "preparing: " + (m4 - m3));
}
重设:3
setDataSource:1
准备:0
重置:3119
setDataSource:2
准备:1
因此,显然,第一个调用reset
被阻止了asynchronous preparing
(当我等到第一个流开始然后channelChanged()
再次调用时,一切都很好)。
有什么想法如何解决问题?我应该在单独的线程中执行整个方法吗?基本上,我想避免这种情况,因为这似乎不是一种好的编码风格,并且可能会引起一些其他问题,例如,当用户尝试再次启动播放器时,但播放器仍处于该reset
方法中,而另一方面似乎在等待asyncPrepare
方法。尚不清楚玩家的行为方式…
还有其他好的解决方案吗?
MediaPlayer是一个棘手的混蛋。我建议您看一下示例应用程序,其中的MediaPlayer不良设计可以通过查看为确保一致的媒体播放体验而必须编写的乱七八糟的代码而变得明显。
如果有什么需要,在查看示例之后,您会发现当他们想要跳过曲目时,他们实际上会 重置 并释放……
mPlayer.reset();
mPlayer.release();
…以及以后准备加载新曲目时…
try {
mPlayer.reset();
mPlayer.setDataSource(someUrl);
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
//bam!
}
});
mPlayer.prepareAsync();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
我添加了try /
catch,因为在某些设备/操作系统版本上,MediaPlayer比其他版本差,有时它只是做一些奇怪的事情。您应该具有能够对这些情况做出反应的接口/侦听器
更新 :
这是我停止(或暂停)音乐播放时使用的一种方法(主要是从示例应用程序中获取,该程序正在服务中运行,并且已对其进行了修改以适合我自己的应用程序,但仍然可以)。
stop
和都使用第一种方法pause
,前者通过true
,后者false
/**
* Releases resources used by the service for playback. This includes the "foreground service"
* status and notification, the wake locks and possibly the MediaPlayer.
*
* @param releaseMediaPlayer Indicates whether the Media Player should also be released or not
*/
void relaxResources(boolean releaseMediaPlayer) {
stopForeground(true);
stopMonitoringPlaybackProgress();
// stop and release the Media Player, if it's available
if (releaseMediaPlayer && mPlayer != null) {
mPlayer.reset();
mPlayer.release();
mPlayer = null;
}
// we can also release the Wifi lock, if we're holding it
if (mWifiLock.isHeld()) {
mWifiLock.release();
}
}
这是以下内容的一部分processPauseRequest()
:
if (mState == State.Playing) {
// Pause media player and cancel the 'foreground service' state.
mState = State.Paused;
mPlayer.pause();
dispatchBroadcastEvent(ServiceConstants.EVENT_AUDIO_PAUSE);//notify broadcast receivers
relaxResources(false); // while paused, we always retain the mp and notification
这是processStopRequest()
(简化)的一部分:
void processStopRequest(boolean force, final boolean stopSelf) {
if (mState == State.Playing || mState == State.Paused || force) {
mState = State.Stopped;
// let go of all resources...
relaxResources(true);
currentTrackNotification = null;
giveUpAudioFocus();
}
}
现在,核心部分是下一个/跳过…
这就是我的工作
void processNextRequest(final boolean isSkipping) {
processStopRequest(true, false); // THIS IS IMPORTANT, WE RELEASE THE MP HERE
mState = State.Retrieving;
dispatchBroadcastEvent(ServiceConstants.EVENT_TRACK_INFO_LOAD_START);
// snipped but here you retrieve your next track and when it's ready…
// you just processPlayRequest() and "start from scratch"
这就是MediaPlayer示例的操作方式(位于samples文件夹中),我没有遇到任何问题。
话虽这么说,但我知道您的意思,当您说整个过程都受阻时,我已经看到了,这是MP的错误。如果您收到ANR,我想查看它的日志。
作为记录,这是我“开始演奏”的方式(已省略了许多自定义代码,但您可以看到MP的东西):”
/**
* Starts playing the next song.
*/
void beginPlaying(Track track) {
mState = State.Stopped;
relaxResources(false); // release everything except MediaPlayer
try {
if (track != null) {
createMediaPlayerIfNeeded();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(track.audioUrl);
} else {
processStopRequest(true, false); // stop everything!
return;
}
mState = State.Preparing;
setUpAsForeground(); //service
/* STRIPPED ALL CODE FROM REMOTECONTROLCLIENT, AS IT ADDS A LOT OF NOISE :) */
// starts preparing the media player in the background. When it's done, it will call
// our OnPreparedListener (that is, the onPrepared() method on this class, since we set
// the listener to 'this').
// Until the media player is prepared, we *cannot* call start() on it!
mPlayer.prepareAsync();
// We are streaming from the internet, we want to hold a Wifi lock, which prevents
// the Wifi radio from going to sleep while the song is playing.
if (!mWifiLock.isHeld()) {
mWifiLock.acquire();
}
} catch (IOException ex) {
Log.e("MusicService", "IOException playing next song: " + ex.getMessage());
ex.printStackTrace();
}
}
最后一点,我注意到当音频流或源不可用或不可靠时,就会发生“阻止所有内容的媒体播放器”。
祝好运!让我知道您是否想查看任何特定内容。
问题内容: 我在修改Python和集合类型。 最初,我认为它将提供比更好的查找性能,因为它是不变的,因此可以利用存储项目的结构。 但是,对于以下实验,情况似乎并非如此: 我使用CPython和PyPy执行了此代码,结果如下: 在CPython和PyPy中,查找性能似乎实际上要慢一些。有人知道为什么会这样吗?我没有研究实现。 问题答案: 的和实现在很大程度上共享; a只是一个添加了变异方法的a ,具
我使用甲骨文表格10g。它是基于web的甲骨文表单应用程序。我想从Oracle窗体10g生成Excel报表。我配置了WEBUTIL并使用CLIENT_OLE2包。在触发器WHEN-BUTTON-PRESSED中声明的过程。当按下按钮时,突然表单冻结,他们什么也做不了。退出按钮和菜单选项停止工作。它不提供任何信息,也不做任何操作。 程序代码:
问题内容: 这是一个片段 我正在使用和作为文本框。文本框应显示“ Hello”,然后等待一秒钟,但是,当我尝试执行此操作时,它会等待一秒钟,然后放置“ Hello”一词,这不是我想要的。 我不确定为什么会这样,因为我将其按逻辑顺序放置。如果有人可以帮助我,那就太好了。 编辑: 有谁知道替代方案,所以我可以使用“延迟”效果吗? 问题答案: 永远不要从Swing事件线程中调用Thread.sleep(
我一直试图使这个应用程序,将产生一个折线图后,我点击"添加新数据项"按钮。现在,在我点击按钮后,什么都没发生(gui冻结),在我最大化框架后,图形出现在框架内,这意味着我的程序工作了,但我不知道为什么我的gui冻结了。我见过类似的问题,人们回答说必须引入一个新的线程来处理不同的拍摄,我也尝试过,但它仍然不起作用,只是让情况变得更糟。有人知道我犯了什么错误吗?这是我的代码: 谢谢你!
问题内容: 我正在尝试使用Swing和ACM交互程序制作一个非常简单的程序。它直接从课堂讲义中获取,但在我的计算机上不起作用。当我运行它时,它可以正常运行约半秒钟,然后短暂闪烁,重新加载,然后所有按钮和文本字段功能都丢失。这是代码: 如果有帮助,我将在运行Mac OSX 10.8.4的2010年中的Mac Pro上将Java SE 1.6与Eclipse Helios Service Releas
当数据被不可变地借用时,它还会冻结(freeze)。已冻结(frozen)数据无法通过原始对象来修改,直到指向这些数据的所有引用离开作用域为止。 fn main() { let mut _mutable_integer = 7i32; { // 借用 `_mutable_integer` let _large_integer = &_mutable_