注意
本文封裝是在android音視頻指南-MediaPlayer概述上進(jìn)行的2次開發(fā)。二次封裝完成后,我提供了正在播放、暫停播放、重置、播放完成、媒體流裝載完成、媒體流加載中、異常錯(cuò)誤等的狀態(tài)返回
業(yè)務(wù)需求
需要對(duì)音樂媒體類進(jìn)行播放,如果需要播放的音樂本地緩存沒有,需要先下載,然后加載音樂。如果有本地緩存的音樂,直接從本地緩存里面讀取,然后加載最后播放
使用說明
1、你需要在自己的Activity或者Fragment去 implements PlaybackInfoListener 接口
MediaPlayerHolder mediaPlayerIngHolder = new MediaPlayerHolder();
mediaPlayerIngHolder.setmPlaybackInfoListener(this);//設(shè)置監(jiān)聽
2、如果是要加載網(wǎng)絡(luò)音樂(我建議先下載下來),或者是本地音樂,需要調(diào)用
mediaPlayerIngHolder.loadMedia(path);//加載音樂,不是屬于播放的狀態(tài)
mediaPlayerIngHolder.play();//開始播放,注意:需要等到onStateChanged == PLAYSTATUS4才可以調(diào)用這個(gè)方法
3、如果不需要播放了,需要釋放資源
mediaPlayerIngHolder.release();
mediaPlayerIngHolder = null;
接口回調(diào)說明
void onTotalDuration(int duration);//返回音樂的總時(shí)長(zhǎng)
void onPositionChanged(int position);//當(dāng)播放的進(jìn)度
void onStateChanged(int state);//記錄當(dāng)前的狀態(tài)
void onPlaybackCompleted();//播放完成回調(diào)
學(xué)習(xí)總結(jié)
1、每次調(diào)用mediaPlayerIngHolder.loadMedia方法,都需要 mMediaPlayer.reset(),這樣是防止再次添加進(jìn)來出現(xiàn)崩潰信息
2、為了避免阻塞主線程,預(yù)加載音樂需要使用mMediaPlayer.prepareAsync();預(yù)加載完成才可以使用mMediaPlayer.start();播放音樂
代碼展示
/**
* @date: 2019/6/21 0021
* @author: gaoxiaoxiong
* @description:播放回調(diào)
**/
public interface PlaybackInfoListener {
void onTotalDuration(int duration);//總時(shí)長(zhǎng)
void onPositionChanged(int position);//當(dāng)前時(shí)長(zhǎng)進(jìn)度
void onStateChanged(int state);//記錄當(dāng)前的狀態(tài)
void onPlaybackCompleted();//播放完成回調(diào)
}
public interface PlayerAdapterListener {
void loadMedia(String musiUrl);//加載媒體資源
void release();//釋放資源
boolean isPlaying();//判斷是否在播放
void play();//開始播放
void reset();//重置
void pause();//暫停
void medisaPreparedCompled();//完成媒體流的裝載
void seekTo(int position);//滑動(dòng)到某個(gè)位置
}
public class MediaPlayerHolder implements PlayerAdapterListener{
public static int PLAYSTATUS0=0;//正在播放
public static int PLAYSTATUS1=1;//暫停播放
public static int PLAYSTATUS2=2;//重置
public static int PLAYSTATUS3=3;//播放完成
public static int PLAYSTATUS4=4;//媒體流裝載完成
public static int PLAYSTATUS5=5;//媒體流加載中
public static int PLAYSTATUSD1=-1;//錯(cuò)誤
public int PLAYBACK_POSITION_REFRESH_INTERVAL_MS = 500;
private String TAG = MediaPlayerHolder.class.getSimpleName();
private MediaPlayer mMediaPlayer;
private ScheduledExecutorService mExecutor;//開啟線程
private PlaybackInfoListener mPlaybackInfoListener;
private Runnable mSeekbarPositionUpdateTask;
private String musiUrl;//音樂地址,可以是本地的音樂,可以是網(wǎng)絡(luò)的音樂
public void setmPlaybackInfoListener(PlaybackInfoListener mPlaybackInfoListener) {
this.mPlaybackInfoListener = mPlaybackInfoListener;
}
/**
* @date: 2019/6/21 0021
* @author: gaoxiaoxiong
* @description:初始化MediaPlayer
**/
private void initializeMediaPlayer(){
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
//注冊(cè),播放完成后的監(jiān)聽
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
stopUpdatingCallbackWithPosition(true);
if (mPlaybackInfoListener != null) {
mPlaybackInfoListener.onStateChanged(PLAYSTATUS3);
mPlaybackInfoListener.onPlaybackCompleted();
}
}
});
//監(jiān)聽媒體流是否裝載完成
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
medisaPreparedCompled();
}
});
/**
* @date: 2019/6/21 0021
* @author: gaoxiaoxiong
* @description:監(jiān)聽媒體錯(cuò)誤信息
**/
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
if (mPlaybackInfoListener!=null){
mPlaybackInfoListener.onStateChanged(PLAYSTATUSD1);
}
Log.d(TAG, "OnError - Error code: " + what + " Extra code: " + extra);
switch (what) {
case -1004:
Log.d(TAG, "MEDIA_ERROR_IO");
break;
case -1007:
Log.d(TAG, "MEDIA_ERROR_MALFORMED");
break;
case 200:
Log.d(TAG, "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK");
break;
case 100:
Log.d(TAG, "MEDIA_ERROR_SERVER_DIED");
break;
case -110:
Log.d(TAG, "MEDIA_ERROR_TIMED_OUT");
break;
case 1:
Log.d(TAG, "MEDIA_ERROR_UNKNOWN");
break;
case -1010:
Log.d(TAG, "MEDIA_ERROR_UNSUPPORTED");
break;
}
switch (extra) {
case 800:
Log.d(TAG, "MEDIA_INFO_BAD_INTERLEAVING");
break;
case 702:
Log.d(TAG, "MEDIA_INFO_BUFFERING_END");
break;
case 701:
Log.d(TAG, "MEDIA_INFO_METADATA_UPDATE");
break;
case 802:
Log.d(TAG, "MEDIA_INFO_METADATA_UPDATE");
break;
case 801:
Log.d(TAG, "MEDIA_INFO_NOT_SEEKABLE");
break;
case 1:
Log.d(TAG, "MEDIA_INFO_UNKNOWN");
break;
case 3:
Log.d(TAG, "MEDIA_INFO_VIDEO_RENDERING_START");
break;
case 700:
Log.d(TAG, "MEDIA_INFO_VIDEO_TRACK_LAGGING");
break;
}
return false;
}
});
}
}
/**
* @date: 2019/6/24 0024
* @author: gaoxiaoxiong
* @description: 加載媒體資源
**/
@Override
public void loadMedia(String musiUrl) {
if (StringUtils.getInstance().isEmpty(musiUrl)){
Log.i(TAG,"地址為空");
return;
}
if (mPlaybackInfoListener!=null){
mPlaybackInfoListener.onStateChanged(PLAYSTATUS5);
}
this.musiUrl = musiUrl;
initializeMediaPlayer();
try {
mMediaPlayer.reset();//防止再次添加進(jìn)來出現(xiàn)崩潰信息
mMediaPlayer.setDataSource(musiUrl);
mMediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @date: 2019/6/24 0024
* @author: gaoxiaoxiong
* @description:釋放媒體資源
**/
@Override
public void release() {
if (mMediaPlayer != null) {
stopUpdatingCallbackWithPosition(false);
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
/**
* @date: 2019/6/24 0024
* @author: gaoxiaoxiong
* @description:判斷是否正在播放
**/
@Override
public boolean isPlaying() {
if (mMediaPlayer != null) {
return mMediaPlayer.isPlaying();
}
return false;
}
/**
* @date: 2019/6/24 0024
* @author: gaoxiaoxiong
* @description:播放開始
**/
@Override
public void play() {
if (mMediaPlayer != null && !mMediaPlayer.isPlaying()) {
mMediaPlayer.start();
if (mPlaybackInfoListener != null) {
mPlaybackInfoListener.onStateChanged(PLAYSTATUS0);
}
startUpdatingCallbackWithPosition();
}
}
/**
* @date: 2019/6/21 0021
* @author: gaoxiaoxiong
* @description:開啟線程,獲取當(dāng)前播放的進(jìn)度
**/
private void startUpdatingCallbackWithPosition() {
if (mExecutor == null) {
mExecutor = Executors.newSingleThreadScheduledExecutor();
}
if (mSeekbarPositionUpdateTask == null) {
mSeekbarPositionUpdateTask = new Runnable() {
@Override
public void run() {
updateProgressCallbackTask();
}
};
}
mExecutor.scheduleAtFixedRate(
mSeekbarPositionUpdateTask,
0,
PLAYBACK_POSITION_REFRESH_INTERVAL_MS,
TimeUnit.MILLISECONDS
);
}
@Override
public void reset() {
if (mMediaPlayer != null) {
loadMedia(musiUrl);
if (mPlaybackInfoListener != null) {
mPlaybackInfoListener.onStateChanged(PLAYSTATUS2);
}
stopUpdatingCallbackWithPosition(true);
}
}
/**
* @date: 2019/6/24 0024
* @author: gaoxiaoxiong
* @description:暫停
**/
@Override
public void pause() {
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
if (mPlaybackInfoListener != null) {
mPlaybackInfoListener.onStateChanged(PLAYSTATUS1);
}
stopUpdatingCallbackWithPosition(false);
}
}
/**
* @date: 2019/6/21 0021
* @author: gaoxiaoxiong
* @description:更新當(dāng)前的進(jìn)度
**/
private void updateProgressCallbackTask() {
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
try {
int currentPosition = mMediaPlayer.getCurrentPosition();
if (mPlaybackInfoListener != null) {
mPlaybackInfoListener.onPositionChanged(currentPosition);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
/**
* @date: 2019/6/24 0024
* @author: gaoxiaoxiong
* @description:加載完成回調(diào)
**/
@Override
public void medisaPreparedCompled() {
int duration = mMediaPlayer.getDuration();//獲取總時(shí)長(zhǎng)
if (mPlaybackInfoListener != null) {
mPlaybackInfoListener.onTotalDuration(duration);
mPlaybackInfoListener.onPositionChanged(0);
mPlaybackInfoListener.onStateChanged(PLAYSTATUS4);
}
}
/**
* @date: 2019/6/21 0021
* @author: gaoxiaoxiong
* @description:滑動(dòng)播放到某個(gè)位置
**/
@Override
public void seekTo(int position) {
if (mMediaPlayer != null) {
mMediaPlayer.seekTo(position);
}
}
/**
* @date: 2019/6/21 0021
* @author: gaoxiaoxiong
* @description:播放完成回調(diào)監(jiān)聽
**/
private void stopUpdatingCallbackWithPosition(boolean resetUIPlaybackPosition) {
if (mExecutor != null) {
mExecutor.shutdownNow();
mExecutor = null;
mSeekbarPositionUpdateTask = null;
if (resetUIPlaybackPosition && mPlaybackInfoListener != null) {
mPlaybackInfoListener.onPositionChanged(0);
}
}
}
}