Fli*_*xer 9 java android android-ui android-mediaplayer
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));
}
Run Code Online (Sandbox Code Playgroud)
重置:3
setDataSource:1
准备:0
重置:3119
setDataSource:2
准备:1
显然,第一次呼叫reset被阻止asynchronous preparing(当我等到第一个流开始然后channelChanged()再次呼叫时,一切都很好).
任何想法如何解决问题?我应该在一个单独的线程中执行整个方法吗?基本上我想避免这种情况,因为它似乎不是一个好的编码风格,并且可能会引起一些进一步的问题,例如当用户试图再次启动播放器时,但播放器仍然在reset方法中,另一方面似乎在等待这个asyncPrepare方法.目前尚不清楚玩家的表现如何......
还有其他好的解决方案吗?
Mar*_*ini 12
MediaPlayer是一个棘手的混蛋.我建议你看一下示例应用程序,通过查看你必须在其周围编写的代码,以获得一致的媒体播放体验,使MediaPlayer的设计变得明显.
如果有的话,在查看样本之后,您会看到当他们想要跳过一个轨道时,它们实际上会重置并释放...
mPlayer.reset();
mPlayer.release();
Run Code Online (Sandbox Code Playgroud)
......以及稍后他们准备加载新曲目时......
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();
}
Run Code Online (Sandbox Code Playgroud)
我已经添加了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();
}
}
Run Code Online (Sandbox Code Playgroud)
这是以下内容的一部分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
Run Code Online (Sandbox Code Playgroud)
这是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();
}
}
Run Code Online (Sandbox Code Playgroud)
现在核心部分是下一个/跳过......
这就是我做的......
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"
Run Code Online (Sandbox Code Playgroud)
这就是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();
}
}
Run Code Online (Sandbox Code Playgroud)
最后一点,我注意到,当音频流或源不可用或不可靠时,"媒体播放器会阻止所有内容".
祝好运!如果您有任何具体想要的话,请告诉我.
| 归档时间: |
|
| 查看次数: |
8313 次 |
| 最近记录: |