Android MediaPlayer的封裝

注意

本文封裝是在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);
            }
        }
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容