在 stop() 和 prepareAsync() 之后未调用 MediaPlayer onPrepared() 的问题
Problem with MediaPlayer onPrepared() not being called after stop() and prepareAsync()
我首先将媒体播放器加载到合成中 class:
public class MediaPlayerWURI {
private final MediaPlayer mediaPlayer;
final Uri uri;
final ActivityMain activityMain;
boolean isPrepared = true;
MediaPlayerWURI(ActivityMain activityMain, MediaPlayer mediaPlayer, Uri uri){
this.activityMain = activityMain;
this.mediaPlayer = mediaPlayer;
this.uri= uri;
mediaPlayer.setOnPreparedListener(null);
mediaPlayer.setOnErrorListener(null);
mediaPlayer.setOnPreparedListener(new MOnPreparedListener(this));
mediaPlayer.setOnErrorListener(new MOnErrorListener());
}
public void prepareAsync(){
isPrepared = false;
mediaPlayer.prepareAsync();
}
public void start(){
mediaPlayer.start();
}
public void stop(){
isPrepared = false;
mediaPlayer.stop();
}
class MOnPreparedListener implements MediaPlayer.OnPreparedListener{
final MediaPlayerWURI mediaPlayerWURI;
public MOnPreparedListener(MediaPlayerWURI mediaPlayerWURI){
this.mediaPlayerWURI = mediaPlayerWURI;
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayerWURI.isPrepared = true;
}
}
class MOnErrorListener implements MediaPlayer.OnErrorListener {
public MOnErrorListener(){
}
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
activityMain.releaseMediaPlayers();
return false;
}
}
}
传入的媒体播放器是用MediaPlayer.create(getApplicationContext())
创建的,并且启动成功。
以下代码不会触发 onPrepared()
并陷入循环。
mediaPlayerWURI.stop();
mediaPlayerWURI.prepareAsync();
while (!mediaPlayerWURI.isPrepared) { }
mediaPlayerWURI.start();
我已经在另一个线程上尝试 prepareAsync()
:
executorService.submit(new Runnable() {
@Override
public void run() {
mediaPlayerWURI.prepareAsync();
}
});
我猜这是一个线程问题,但我不确定如何处理这个问题,或者它是否是一个线程问题。我的理解是 MediaPlayer 正在另一个线程中准备,并且循环不应该阻止它调用准备好的。我不确定 onPrepare()
是在哪个线程 运行 上,但是从上面来看,我认为这意味着主线程应该 运行 onPrepare()
并且正在等待循环结束。
此外,在构建 MediaPlayer 后调用 onPrepared()
时,我遇到了奇怪的行为。那是正常的吗?我的假设是在准备好的 MediaPlayer 上调用 setOnPrepared()
时调用 onPrepared()
。这意味着侦听器已附加。
问题是在等待 MediaPlayer 准备好时 while (!mediaPlayerWURI.isPrepared) { }
,我正在占用 UI 线程,这与 onPrepared()
使用的线程相同。
为了解决这个问题,我不得不停止占用 UI 线程。我在我的 MediaPlayerWURI 包装器 class 中添加了一个布尔值,指示在准备好的情况下播放 MediaPlayer。
private final MediaPlayer mediaPlayer;
volatile boolean isPrepared;
volatile boolean shouldPlay;
synchronized public void shouldStart(boolean shouldPlay){
if(shouldPlay && isPrepared){
mediaPlayer.start();
} else {
this.shouldPlay = shouldPlay;
}
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
synchronized (mediaPlayerWURI) {
mediaPlayerWURI.isPrepared = true;
if (shouldPlay) {
mediaPlayer.start();
shouldPlay = false;
}
}
}
我首先将媒体播放器加载到合成中 class:
public class MediaPlayerWURI {
private final MediaPlayer mediaPlayer;
final Uri uri;
final ActivityMain activityMain;
boolean isPrepared = true;
MediaPlayerWURI(ActivityMain activityMain, MediaPlayer mediaPlayer, Uri uri){
this.activityMain = activityMain;
this.mediaPlayer = mediaPlayer;
this.uri= uri;
mediaPlayer.setOnPreparedListener(null);
mediaPlayer.setOnErrorListener(null);
mediaPlayer.setOnPreparedListener(new MOnPreparedListener(this));
mediaPlayer.setOnErrorListener(new MOnErrorListener());
}
public void prepareAsync(){
isPrepared = false;
mediaPlayer.prepareAsync();
}
public void start(){
mediaPlayer.start();
}
public void stop(){
isPrepared = false;
mediaPlayer.stop();
}
class MOnPreparedListener implements MediaPlayer.OnPreparedListener{
final MediaPlayerWURI mediaPlayerWURI;
public MOnPreparedListener(MediaPlayerWURI mediaPlayerWURI){
this.mediaPlayerWURI = mediaPlayerWURI;
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayerWURI.isPrepared = true;
}
}
class MOnErrorListener implements MediaPlayer.OnErrorListener {
public MOnErrorListener(){
}
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
activityMain.releaseMediaPlayers();
return false;
}
}
}
传入的媒体播放器是用MediaPlayer.create(getApplicationContext())
创建的,并且启动成功。
以下代码不会触发 onPrepared()
并陷入循环。
mediaPlayerWURI.stop();
mediaPlayerWURI.prepareAsync();
while (!mediaPlayerWURI.isPrepared) { }
mediaPlayerWURI.start();
我已经在另一个线程上尝试 prepareAsync()
:
executorService.submit(new Runnable() {
@Override
public void run() {
mediaPlayerWURI.prepareAsync();
}
});
我猜这是一个线程问题,但我不确定如何处理这个问题,或者它是否是一个线程问题。我的理解是 MediaPlayer 正在另一个线程中准备,并且循环不应该阻止它调用准备好的。我不确定 onPrepare()
是在哪个线程 运行 上,但是从上面来看,我认为这意味着主线程应该 运行 onPrepare()
并且正在等待循环结束。
此外,在构建 MediaPlayer 后调用 onPrepared()
时,我遇到了奇怪的行为。那是正常的吗?我的假设是在准备好的 MediaPlayer 上调用 setOnPrepared()
时调用 onPrepared()
。这意味着侦听器已附加。
问题是在等待 MediaPlayer 准备好时 while (!mediaPlayerWURI.isPrepared) { }
,我正在占用 UI 线程,这与 onPrepared()
使用的线程相同。
为了解决这个问题,我不得不停止占用 UI 线程。我在我的 MediaPlayerWURI 包装器 class 中添加了一个布尔值,指示在准备好的情况下播放 MediaPlayer。
private final MediaPlayer mediaPlayer;
volatile boolean isPrepared;
volatile boolean shouldPlay;
synchronized public void shouldStart(boolean shouldPlay){
if(shouldPlay && isPrepared){
mediaPlayer.start();
} else {
this.shouldPlay = shouldPlay;
}
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
synchronized (mediaPlayerWURI) {
mediaPlayerWURI.isPrepared = true;
if (shouldPlay) {
mediaPlayer.start();
shouldPlay = false;
}
}
}