Activity 結束時釋放 MediaPlayer 拋出 IllegalStateException,堆疊追蹤指向 isPlaying()、getCurrentPosition() 被 MediaController 在釋放後呼叫。
// 按鈕點擊釋放
imageAllBack.setOnClickListener(v -> {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release(); // 釋放後狀態重置
}
finish();
});
// onStop 再次釋放 (重複釋放)
@Override protected void onStop() {
super.onStop();
mediaPlayer.stop();
mediaPlayer.release(); // 崩潰點:MediaController 仍在嘗試存取
}
核心原因:MediaController 內部有 Handler 定期輪詢 MediaPlayer 狀態 (更新進度條),釋放後仍在嘗試存取導致非法狀態。
private void releaseMediaPlayer() {
if (mediaPlayer != null) {
try {
// 1. 先移除 MediaController 回調 (關鍵)
if (mediaController != null) {
mediaController.hide(); // 停止內部 Handler 輪詢
mediaController.setMediaPlayer(null); // 斷開關聯
}
// 2. 停止並釋放
if (mediaPlayer.isPlaying()) mediaPlayer.stop();
mediaPlayer.release();
} catch (IllegalStateException e) {
e.printStackTrace(); // 防禦性捕獲
} finally {
mediaPlayer = null;
mediaController = null;
}
}
}
// 在所有離開點統一呼叫
@Override protected void onStop() {
super.onStop();
releaseMediaPlayer();
}
public void onBackClick(View v) {
releaseMediaPlayer();
finish();
}
public class VideoActivity extends AppCompatActivity implements MediaPlayerControl {
private MediaPlayer mediaPlayer;
private MediaController mediaController;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initMediaPlayer();
}
private void initMediaPlayer() {
mediaPlayer = MediaPlayer.create(this, R.raw.video);
mediaController = new MediaController(this);
mediaController.setMediaPlayer(this);
mediaController.setAnchorView(findViewById(R.id.video_view));
mediaPlayer.setOnPreparedListener(mp -> mediaController.show());
}
// MediaPlayerControl 介面實作
@Override public void start() { mediaPlayer.start(); }
@Override public void pause() { mediaPlayer.pause(); }
@Override public int getDuration() { return mediaPlayer.getDuration(); }
@Override public int getCurrentPosition() { return mediaPlayer.getCurrentPosition(); }
@Override public void seekTo(int pos) { mediaPlayer.seekTo(pos); }
@Override public boolean isPlaying() { return mediaPlayer.isPlaying(); }
@Override public int getBufferPercentage() { return 0; }
@Override public boolean canPause() { return true; }
@Override public boolean canSeekBackward() { return true; }
@Override public boolean canSeekForward() { return true; }
@Override protected void onDestroy() {
super.onDestroy();
releaseMediaPlayer();
}
private void releaseMediaPlayer() {
if (mediaController != null) {
mediaController.hide();
mediaController.setMediaPlayer(null);
}
if (mediaPlayer != null) {
try {
if (mediaPlayer.isPlaying()) mediaPlayer.stop();
mediaPlayer.release();
} catch (Exception e) { e.printStackTrace(); }
finally { mediaPlayer = null; }
}
}
}
onDestroy() 或自訂 release() 方法mediaController.setMediaPlayer(null) 停止內部輪詢try-catch 包裹 release(),檢查 isPlaying() 前確認非 nullnull 防止重複操作