gpt4 book ai didi

安卓媒体播放器 : IllegalStateException when app closes/press back button

转载 作者:行者123 更新时间:2023-11-29 19:28:57 24 4
gpt4 key购买 nike

我使用媒体播放器从 url 流式传输 mp3 音频,现在我可以播放音乐,但是当我按下后退按钮或关闭应用程序时,它崩溃了。谁能帮我找出我的错误。谢谢。

我的代码是:

        private ImageView play, forward, backward;
private MediaPlayer mediaPlayer;
private boolean playing = false;
private ProgressDialog dialog;
private String mp3link;
private SeekBar seekbar;
private Handler handler = new Handler();
private int mediaPos;
private int mediaMax;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String url ="";
initWidgets();

}

private void initWidgets() {
mp3link = "http://loc8app.com/church/uploads/audio/749928ad6fcb7b1aceefdf03bd7a9465.mp3";
play = (ImageView) findViewById(R.id.control);
seekbar = (SeekBar) findViewById(R.id.seekBar);
// forward = (ImageView) findViewById(R.id.playeer_forward);
// backward = (ImageView) findViewById(R.id.playeer_back);
mediaPlayer = new MediaPlayer();
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
playFunction();
}
});

seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(mediaPlayer != null && fromUser){
mediaPlayer.seekTo(progress);
}
}
});
}


private void playFunction() {
if (!playing) {
try {
dialog = ProgressDialog
.show(MainActivity.this,
"",
getString(com.root5solutions.music.R.string.buffering),
true);
dialog.setCancelable(true);
dialog.show();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(mp3link);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

@Override
public void onPrepared(MediaPlayer mp) {
play.setBackgroundResource(R.drawable.pause);
playing = true;
//this is new
mediaPos = mp.getCurrentPosition();
mediaMax = mp.getDuration();

seekbar.setMax(mediaMax);
seekbar.setProgress(mediaPos);
//this line is the error
handler.removeCallbacks(moveSeekBarThread);
handler.postDelayed(moveSeekBarThread, 100);

mp.start();
dialog.dismiss();
}
});
mediaPlayer.prepareAsync();

} catch (Exception e) {
e.printStackTrace();
dialog.dismiss();
}
} else {
play.setBackgroundResource(R.drawable.play);
mediaPlayer.stop();
mediaPlayer.release();
playing = false;
}
}

@Override
public void onBackPressed() {
super.onBackPressed();
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
}

private Runnable moveSeekBarThread = new Runnable() {

public void run() {
if (mediaPlayer.isPlaying()) {
int mediaPos_new = mediaPlayer.getCurrentPosition();
int mediaMax_new = mediaPlayer.getDuration();
seekbar.setMax(mediaMax_new);
seekbar.setProgress(mediaPos_new);

handler.postDelayed(this, 1000); // Looping the thread after 1 second

}

}
};
}

Logcat 显示:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.root.music, PID: 26981
java.lang.IllegalStateException
at android.media.MediaPlayer.isPlaying(Native Method)
at com.root.music.MainActivity$4.run(MainActivity.java:132)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5351)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:947)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:742)

最佳答案

问题似乎是由 moveSeekBarThread 引起的Runnable ,从中引发异常,在 mediaPlayer 之后继续执行在 onBackPressed() 中发布.这导致 isPlaying()正在执行的方法,根据 documentation将导致 IllegalStateException :

if the internal player engine has not been initialized or has been released.

查看moveSeekBarThread , 它似乎被配置为通过将自己发布回 handler 来无休止地重新安排自己Handler有延迟的例子。当用户离开 Activity 时,此过程不会停止,这解释了为什么 moveSeekBarThread继续运行。因此,基于以上所述,一种解决方案可能是确保 moveSeekBarThread 的任何实例在 handler的队列在调用 mediaPlayer.release() 之前被移除当用户离开 Activity 时。

您应该可以通过调用 handler.removeCallbacks(moveSeekBarThread); 来做到这一点在你打电话之前 mediaPlayer.release() .例如如下:

@Override
public void onBackPressed() {
super.onBackPressed();
handler.removeCallbacks(moveSeekBarThread);
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
}

mediaPlayer.release()之前调用应该没问题, 但我认为无论 mediaPlayer 是否都调用它更安全正在玩。这样,如果 Runnable尽管媒体播放器没有启动或停止,但确实以某种方式启动或保持启动状态,Runnable仍将被清除。

顺便说一句,虽然我对 MediaPlayer 没有任何经验, 我碰巧注意到 release 的文档方法有如下说法:

It is considered good practice to call this method when you're done using the MediaPlayer. In particular, whenever an Activity of an application is paused (its onPause() method is called), or stopped (its onStop() method is called), this method should be invoked to release the MediaPlayer object, unless the application has a special need to keep the object around. In addition to unnecessary resources (such as memory and instances of codecs) being held, failure to call this method immediately if a MediaPlayer object is no longer needed may also lead to continuous battery consumption for mobile devices, and playback failure for other applications if no multiple instances of the same codec are supported on a device.

因此,除非在您的情况下特别需要在 Activity 中保留媒体播放器,否则最好在 moveSeekBarThread 中处理发布过程(包括从 handler 中清除 onPause)。或 onStop相反。

希望对您有所帮助!

关于安卓媒体播放器 : IllegalStateException when app closes/press back button,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40603618/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com