setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener):當使用seekTo()設定播放位置的時候回調。
MediaPlayer提示
在使用MediaPlayer的使用過程中,有個小技巧需要說明一下:
1、在使用start()播放流媒體之前,需要裝載流媒體資源。這裡最好使用prepareAsync()用非同步方式裝載流媒體資源。因為流媒體資源的裝載是會消耗系統資源的,在一些硬體不理想的裝置上,如果使用prepare()同步的方式裝載資源,可能會造成UI介面的卡頓,這是非常影響用於體驗的。因為推薦使用非同步裝載的方式,為了避免還沒有裝載完成就調用start()而報錯的問題,需要綁定MediaPlayer.setOnPreparedListener()事件,它將在非同步裝載完成之後回調。非同步裝載還有一個好處就是避免裝載逾時引發ANR((Application Not Responding)錯誤。
1 mediaPlayer = new MediaPlayer(); 2 mediaPlayer.setDataSource(path); 3 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 4 5 // 通過非同步方式裝載媒體資源 6 mediaPlayer.prepareAsync(); 7 mediaPlayer.setOnPreparedListener(new OnPreparedListener() { 8 @Override 9 public void onPrepared(MediaPlayer mp) {10 // 裝載完畢回調11 mediaPlayer.start();12 }13 });
2、使用完MediaPlayer需要回收資源。MediaPlayer是很消耗系統資源的,所以在使用完MediaPlayer,不要等待系統自動回收,最好是主動回收資源。
1 if (mediaPlayer != null && mediaPlayer.isPlaying()) {2 mediaPlayer.stop();3 mediaPlayer.release();4 mediaPlayer = null;5 }
3、使用MediaPlayer最好使用一個Service來使用,並且在Service的onDestory()方法中回收MediaPlayer資源,實際上,就算是直接使用Activity承載MediaPlayer,也最好在銷毀的時候判斷一下MediaPlayer是否被回收,如果未被回收,回收其資源,因為底層調用的native方法,如果不銷毀還是會在底層繼續播放,而承載的組件已經被銷毀了,這個時候就無法擷取到這個MediaPlayer進而控制它。
1 @Override2 protected void onDestroy() {3 if (mediaPlayer != null && mediaPlayer.isPlaying()) {4 mediaPlayer.stop();5 mediaPlayer.release();6 mediaPlayer = null;7 }8 super.onDestroy();9 }
4、對於單曲迴圈之類的操作,除了可以使用setLooping()方法進行設定之外,還可以為MediaPlayer註冊回呼函數,MediaPlayer.setOnCompletionListener(),它會在MediaPlayer播放完畢被回調。
1 // 設定迴圈播放 2 // mediaPlayer.setLooping(true); 3 mediaPlayer.setOnCompletionListener(new OnCompletionListener() { 4 5 @Override 6 public void onCompletion(MediaPlayer mp) { 7 // 在播放完畢被回調 8 play(); 9 }10 });
5、因為MediaPlayer一直操作的是一個流媒體,所以無可避免的可能一段流媒體資源,前半段可以正常播放,而中間一段因為解析或者源檔案錯誤等問題,造成中間一段無法播放問題,需要我們處理這個錯誤,否則會影響Ux(使用者體驗)。可以為MediaPlayer註冊回呼函數setOnErrorListener()來設定出錯之後的解決辦法,一般重新播放或者播放下一個流媒體即可。
1 mediaPlayer.setOnErrorListener(new OnErrorListener() {2 3 @Override4 public boolean onError(MediaPlayer mp, int what, int extra) {5 play();6 return false;7 }8 });
Demo--一個簡單的MP3播放器
上面已經介紹了MediaPlayer播放一段音頻檔案的所有需要用到的內容。下面通過一個簡單的Demo來示範如何使用MediaPlayer播放一個SD卡上的MP3檔案。操作MediaPlayer應該放在Service中完成,這裡為了簡單,使用Activity直接操作MediaPlayer。代碼注釋裡寫的很清楚裡,這裡不再累述。
執行這個樣本需要在/sdcard/目錄下存在xm.mp3的檔案。
1 package cn.bgxt.mediaplayerdemo; 2 3 import java.io.File; 4 import android.media.AudioManager; 5 import android.media.MediaPlayer; 6 import android.media.MediaPlayer.OnCompletionListener; 7 import android.media.MediaPlayer.OnErrorListener; 8 import android.media.MediaPlayer.OnPreparedListener; 9 import android.os.Bundle; 10 import android.app.Activity; 11 import android.view.View; 12 import android.widget.Button; 13 import android.widget.EditText; 14 import android.widget.Toast; 15 16 public class MainActivity extends Activity { 17 private EditText et_path; 18 private Button btn_play, btn_pause, btn_replay, btn_stop; 19 private MediaPlayer mediaPlayer; 20 21 @Override 22 protected void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 setContentView(R.layout.activity_main); 25 26 et_path = (EditText) findViewById(R.id.et_path); 27 btn_play = (Button) findViewById(R.id.btn_play); 28 btn_pause = (Button) findViewById(R.id.btn_pause); 29 btn_replay = (Button) findViewById(R.id.btn_replay); 30 btn_stop = (Button) findViewById(R.id.btn_stop); 31 32 btn_play.setOnClickListener(click); 33 btn_pause.setOnClickListener(click); 34 btn_replay.setOnClickListener(click); 35 btn_stop.setOnClickListener(click); 36 } 37 38 private View.OnClickListener click = new View.OnClickListener() { 39 40 @Override 41 public void onClick(View v) { 42 43 switch (v.getId()) { 44 case R.id.btn_play: 45 play(); 46 break; 47 case R.id.btn_pause: 48 pause(); 49 break; 50 case R.id.btn_replay: 51 replay(); 52 break; 53 case R.id.btn_stop: 54 stop(); 55 break; 56 default: 57 break; 58 } 59 } 60 }; 61 /** 62 * 播放音樂 63 */ 64 protected void play() { 65 String path = et_path.getText().toString().trim(); 66 File file = new File(path); 67 if (file.exists() && file.length() > 0) { 68 try { 69 mediaPlayer = new MediaPlayer(); 70 // 設定指定的流媒體地址 71 mediaPlayer.setDataSource(path); 72 // 設定音頻流的類型 73 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 74 75 // 通過非同步方式裝載媒體資源 76 mediaPlayer.prepareAsync(); 77 mediaPlayer.setOnPreparedListener(new OnPreparedListener() { 78 @Override 79 public void onPrepared(MediaPlayer mp) { 80 // 裝載完畢 開始播放流媒體 81 mediaPlayer.start(); 82 Toast.makeText(MainActivity.this, "開始播放", 0).show(); 83 // 避免重複播放,把播放按鈕設定為不可用 84 btn_play.setEnabled(false); 85 } 86 }); 87 // 設定迴圈播放 88 // mediaPlayer.setLooping(true); 89 mediaPlayer.setOnCompletionListener(new OnCompletionListener() { 90 91 @Override 92 public void onCompletion(MediaPlayer mp) { 93 // 在播放完畢被回調 94 btn_play.setEnabled(true); 95 } 96 }); 97 98 mediaPlayer.setOnErrorListener(new OnErrorListener() { 99 100 @Override101 public boolean onError(MediaPlayer mp, int what, int extra) {102 // 如果發生錯誤,重新播放103 replay();104 return false;105 }106 });107 } catch (Exception e) {108 e.printStackTrace();109 Toast.makeText(this, "播放失敗", 0).show();110 }111 } else {112 Toast.makeText(this, "檔案不存在", 0).show();113 }114 115 }116 /**117 * 暫停118 */119 protected void pause() {120 if (btn_pause.getText().toString().trim().equals("繼續")) {121 btn_pause.setText("暫停");122 mediaPlayer.start();123 Toast.makeText(this, "繼續播放", 0).show();124 return;125 }126 if (mediaPlayer != null && mediaPlayer.isPlaying()) {127 mediaPlayer.pause();128 btn_pause.setText("繼續");129 Toast.makeText(this, "暫停播放", 0).show();130 }131 132 }133 134 /**135 * 重新播放136 */137 protected void replay() {138 if (mediaPlayer != null && mediaPlayer.isPlaying()) {139 mediaPlayer.seekTo(0);140 Toast.makeText(this, "重新播放", 0).show();141 btn_pause.setText("暫停");142 return;143 } 144 play();145 }146 147 /**148 * 停止播放149 */150 protected void stop() {151 if (mediaPlayer != null && mediaPlayer.isPlaying()) {152 mediaPlayer.stop();153 mediaPlayer.release();154 mediaPlayer = null;155 btn_play.setEnabled(true);156 Toast.makeText(this, "停止播放", 0).show();157 }158 159 }160 161 @Override162 protected void onDestroy() {163 // 在activity結束的時候回收資源164 if (mediaPlayer != null && mediaPlayer.isPlaying()) {165 mediaPlayer.stop();166 mediaPlayer.release();167 mediaPlayer = null;168 }169 super.onDestroy();170 }171 }
效果展示: