android 使用mediaplayer播放網絡音樂

關於mediaplayer 的介紹

MediaPlayer是Android自帶的一個多媒體播放類,可以播放音視頻流或者本地音視頻文件。MediaPlayer方法的調用需要在一定的狀態下,下圖是一個MediaPlayer對象被支持的播放控制操作驅動的聲明週期和狀態。其中,橢圓代表MediaPlayer可能駐留的狀態,弧線表示驅動MediaPlayer在各個狀態之間遷移的播放控制操作。這裏有兩種類型的弧線。由單箭頭開始的弧線代表同步方法調用,而以雙箭頭開頭的弧線代表異步方法調用。圖片介紹來源於官方文。
 

封裝一個管理類,用於播放在線的音樂

由於播放在線音樂時可能會因爲網絡的原因,導致耗時比較大,這裏使用了AndroidVideoCache這個庫,來實現音頻的緩存,下次再播放的時候就可以避免再次從網絡獲取。
AndroidVideoCache地址:https://github.com/danikula/AndroidVideoCache以下是封裝的管理類的代碼:
AudioManager.java

public class AudioManager implements MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener{

    private static AudioManager INSTANCE;

    private MediaPlayer mMediaPlayer;

    private Context mContext;

    /**
     * 是否正在準備
     */
    private boolean isPreparing = false;

    /**
     * 當前準備
     */
    private AudioBean preBean;

    private Handler mHandler;

    /**
     * 最後的一個操作,如果是prepareing的時候,所有操作都保存在這裏
     */
    private AudioBean curBean;

    private AudioManager(Context context){
        this.mContext = context;
        initMediaPlayer();
        mHandler = new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                preparing();
            }
        };
    }

    public static AudioManager getInstance(Context context){
        if (INSTANCE == null) {
            synchronized(AudioManager.class) {
                if (INSTANCE == null){
                    INSTANCE = new AudioManager(context);
                }
            }
        }
        return INSTANCE;
    }

    /**
     * 播放Assest目錄下的音頻
     * @param name
     */
    public void playAssertAudio(String name) {
        if(mMediaPlayer != null && mContext != null) {
            try {
                mMediaPlayer.reset();
                AssetFileDescriptor fd = mContext.getAssets().openFd(name);
                mMediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
                mMediaPlayer.prepareAsync();
                mMediaPlayer.setOnPreparedListener(this);
                mMediaPlayer.setOnCompletionListener(this);

                mMediaPlayer.setOnErrorListener(this);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 停止播放
     */
    protected void stopAssertAudio() {
        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
            mMediaPlayer.stop();
            Toast.makeText(mContext, "停止播放", Toast.LENGTH_SHORT).show();
        }
    }


    /**
     * 播放音頻
     * @param url
     */
    public void playAudio(final String url) {
        if(isPreparing) {
            setCurdata(url, AudioBean.START, true);
            return ;
        }
        if(mMediaPlayer != null && mContext != null) {
            try {
                setPredata(url, AudioBean.START, true);

                mMediaPlayer.reset();
                HttpProxyCacheServer proxy = HttpProxyCacheUtil.getAudioProxy(mContext);
                mMediaPlayer.setDataSource(proxy.getProxyUrl(url));
                isPreparing = true;
                mMediaPlayer.prepareAsync();
                mMediaPlayer.setOnPreparedListener(this);
                mMediaPlayer.setOnCompletionListener(this);

                mMediaPlayer.setOnErrorListener(this);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 釋放MediaPlayer
     */
    public void clear() {
        if (mMediaPlayer != null) {
            if(mMediaPlayer.isPlaying())
                mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    /**
     * 停止播放
     */
    public void stopAudio(String url) {
        if(isPreparing) { // 如果mediaplayer當前正在準備數據,則只保留數據
            setCurdata(url, AudioBean.STOP, true);
        } else {
            if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
                mMediaPlayer.stop();
            }
        }
    }

    /**
     * 準備播放
     */
    @Override
    public void onPrepared(MediaPlayer mp) {
        mHandler.sendEmptyMessageDelayed(1, 0); // 模擬mediaplayer準備數據中間時長,延時
    }

    private void preparing() {
        isPreparing = false;
        if(preBean != null && curBean != null && curBean.isNeed()) { // 需要處理
            // 判斷url是否一樣,
            if(preBean.getUrl().equals(curBean.getUrl())) { // 比如點擊暫停,又點擊開始
                if(curBean.getStatus() == AudioBean.START && curBean.isNeed()) { // 如果同一個url並且需要播放,就直接start,比如prepare的時候,點擊了暫停,在點擊開始,同一個音頻
                    start();
                } else { // 同一個url,如果是停止,就直接不處理,後面把isNeed設置成false
                }
            } else { // 如果不同url,說明點擊了另外的音頻,
                if(curBean.getStatus() == AudioBean.START && curBean.isNeed()) { // 重新play新的url
                    playAudio(curBean.getUrl());
                } else { // 如果停止的話無需處理
                }
            }
            setCurdata("", AudioBean.STOP, false);
        } else { // 如果最後一次操作不需要處理,則走正常流程
            start();
        }
    }

    /**
     * 完成
     */
    @Override
    public void onCompletion(MediaPlayer mp) {
    }

    /**
     * 播放錯誤
     */
    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        return false;
    }

    /**
     * init
     */
    private void initMediaPlayer() {
        if(mMediaPlayer != null) {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        mMediaPlayer = new MediaPlayer();
        mMediaPlayer.setAudioStreamType(android.media.AudioManager.STREAM_MUSIC);
    }

    /**
     * 開始播放
     */
    private void start() {
        if (mMediaPlayer != null)
            mMediaPlayer.start();
    }

    /**
     * 保存prepare前的操作
     */
    private void setPredata(String url, int status, boolean isNeed) {
        if(preBean == null) {
            preBean = new AudioBean();
        }
        if(preBean != null) {
            preBean.setUrl(url);
            preBean.setStatus(status);
            preBean.setNeed(isNeed);
        }
    }

    /**
     * 保存prepare中的操作
     */
    private void setCurdata(String url, int status, boolean isNeed) {
        if(curBean == null) {
            curBean = new AudioBean();
        }
        if(curBean != null) {
            curBean.setUrl(url);
            curBean.setStatus(status);
            curBean.setNeed(isNeed);
        }
    }


}

這個管理類實現了播放在線音頻的功能,如果有什麼問題,歡迎留言交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章