一个音频播放的辅助类

469 阅读8分钟

说明:

  • 音频控件持有类 - 单例实现
  • 功能:
    1. 播放播放
    1. 暂停播放
    1. 停止播放
    1. 开始一段音频时,暂停其他所有正在播放
    1. 全局的进度回调定时器,
    1. 单独获取音频时长时应该先调用 getMp3Length 方法获取,结果会在回调中给出,单位是秒.假如此方法返回的结果是-1,则需要调用pendPlay方法再次获取一次音频时长
    1. 音频时长的获取需要一个第三放库 jaudiotagger-2.2.6-PATHRIK 作为基础.这是一个开源项目
    1. 播放速度调整-setSpeed
    1. 获得当前播放速度-getCurrentSpeed
  • 10.是否正在播放-isPlaying
  • 11.获得频繁的播放位置回调-getFrequentlyPosition,只需要在监听onPlaying方法中调用此方法即可无需取消。即可做到按您定制的时间进行进度回调。暂停时自动取消。
import android.media.AudioManager;
import android.os.Build;
import android.text.TextUtils;
import android.view.Gravity;

import com.koo.ielt.utils.function.Log;
import com.koo.ielt.utils.function.ToastUtils;
import com.koo.ielt.utils.function.rx.RxJavaCallBack;
import com.koo.ielt.utils.function.rx.RxJavaManager;

import org.jaudiotagger.audio.mp3.MP3AudioHeader;
import org.jaudiotagger.audio.mp3.MP3File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import tvgk.danmaku.ijk.media.player.IMediaPlayer;
import tvgk.danmaku.ijk.media.player.IjkMediaPlayer;

/**
 * 作者: zhou
 * 时间:
 * 说明:
 * 音频控件持有类 - 单例实现  用于替代 MediaPlayerHolder2
 *
 * 注意:
 * 1. key在播放时的唯一性,如果是同一列表,key值应该唯一.这样在播放列表中下一个音频的时候,上一个音频才会被停止,以此避免创建多个MediaPlayer.
 * 否则会创建一个新的MediaPlayer但是上一个播放依然会暂停.
 * 2. 所有播放都需要在最后destory界面的时候release方法来进行销毁map中保存的MediaPlayer
 *
 * 功能:
 * 1. 播放播放
 * 2. 暂停播放
 * 3. 停止播放
 * 4. 开始一段音频时,暂停其他所有正在播放
 * 5. 全局的进度回调定时器,
 * 6. 单独获取音频时长时应该先调用 getMp3Length 方法获取,结果会在回调中给出,单位是秒.假如此方法返回的结果是-1,则需要调用pendPlay方法再次获取一次音频时长
 * 7. 音频时长的获取需要一个第三放库 jaudiotagger-2.2.6-PATHRIK 作为基础.这是一个开源项目
 * 8. 播放速度调整-setSpeed
 * 9. 获得当前播放速度-getCurrentSpeed
 * 10.是否正在播放-isPlaying
 * 11.获得频繁的播放位置回调-getFrequentlyPosition,只需要在监听onPlaying方法中调用此方法即可无需取消。即可做到按您定制的时间进行进度回调。暂停时自动取消。
 */
public class AudioPlayHelper {
    private String TAG = "AudioPlayHelper";

    /**
     * 更新进度的间隔
     */
    private final int peridTime = 1000;
    private Disposable mDisposable;
    private Disposable mFrequentlyDisposable;

    private static AudioPlayHelper audioPlayHelper = new AudioPlayHelper();
    /**
     * 装MediaPlayer的Map,播放的时候add进去,界面销毁的时候remove
     * key1,tag
     * key2,url
     * value mediaHolder
     */
    private HashMap<String, HashMap<String, MediaHolder>> mMediaPlayerMap = new HashMap<>();

//    private AudioManager mAudioManager = (AudioManager) IeltsApp.getInstance().getBaseContext().getSystemService(AUDIO_SERVICE);


    private AudioPlayHelper() {

    }

    public static AudioPlayHelper getInstance() {
        return audioPlayHelper;
    }

    private void addMediaPlayer(String tag, String key, MediaHolder mediaHolder) {
        if (mMediaPlayerMap.get(tag) != null) {
            mMediaPlayerMap.get(tag).put(key, mediaHolder);
        } else {
            HashMap<String, MediaHolder> map = new HashMap<>();
            map.put(key, mediaHolder);
            mMediaPlayerMap.put(tag, map);
        }
    }

    private void removeMediaPlayer(String tag, String key) {
        if(mMediaPlayerMap!=null && mMediaPlayerMap.get(tag)!=null){
            mMediaPlayerMap.get(tag).remove(key);
        }
    }
    private void removeMediaPlayerByTag(String tag) {
        if(mMediaPlayerMap!=null && mMediaPlayerMap.get(tag)!=null){
            mMediaPlayerMap.remove(tag);
        }
    }

    /**
     * 释放媒体资源
     **/
    public void release(String tag, String key) {
        if (isPlayerNotNull(tag, key)) {
            mMediaPlayerMap.get(tag).get(key).mediaPlayer.stop();
            mMediaPlayerMap.get(tag).get(key).mediaPlayer.release();
            removeMediaPlayer(tag, key);
        }
        stopTimer();
    }

    /**
     * 设置播放速度
     **/
    public boolean setSpeed(String tag, String key,float speed) {
        if (isPlayerNotNull(tag, key)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                mMediaPlayerMap.get(tag).get(key).mediaPlayer.setSpeed(speed);
                return true;
            } else {
                ToastUtils.show("对不起请升级手机系统至Android6.0及以上");
                return false;
            }
        }
        return false;
    }

    /**
     * 获得当前播放速度
     **/
    public float getCurrentSpeed(String tag, String key) {
        if (isPlayerNotNull(tag, key)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                return mMediaPlayerMap.get(tag).get(key).mediaPlayer.getSpeed(1);
            }
        }
        return 1.0f;
    }

    /**
     * 释放媒体资源
     **/
    public long getCurrentPosition(String tag, String key) {
        if (isPlayerNotNull(tag, key)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                return mMediaPlayerMap.get(tag).get(key).mediaPlayer.getCurrentPosition();
            }
        }
        return 0;
    }

    /**
     * 获得某个音频的快速进度回调,用于做拦截进度从而定制自己相对应的功能,比如说单句循环。
     * @param tag
     * @param key
     * @param time 自定义每隔多久进行一次进度回调
     * @param progress
     */
    public void getFrequentlyPosition(String tag,String key,int time,AudioPlayPosition progress){
        if(mFrequentlyDisposable==null){
            Observable.interval(time, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<Long>() {
                        @Override
                        public void onSubscribe(Disposable disposable) {
                            mFrequentlyDisposable = disposable;
                        }

                        @Override
                        public void onNext(Long number) {
                            if(isPlayerNotNull(tag,key)){
                                IjkMediaPlayer player = mMediaPlayerMap.get(tag).get(key).mediaPlayer;
                                if(player.isPlaying()){
                                    progress.onPosition(player.getCurrentPosition());
                                }else{
                                    mFrequentlyDisposable.dispose();
                                    mFrequentlyDisposable = null;
                                }
                            }else{
                                mFrequentlyDisposable.dispose();
                                mFrequentlyDisposable = null;
                            }
                            Log.i("----->","AudioPlayHelper-timer-running");
                        }

                        @Override
                        public void onError(Throwable e) {

                        }

                        @Override
                        public void onComplete() {

                        }
                    });

        }

    }

    /**
     * 释放指定tag的播放
     */
    public void releaseByTag(String tag) {
        if(mMediaPlayerMap!=null && mMediaPlayerMap.get(tag)!=null){
            for (MediaHolder mediaHolder : mMediaPlayerMap.get(tag).values()) {
                if (mediaHolder != null && mediaHolder.mediaPlayer != null && mediaHolder.mediaPlayer.isPlaying()) {
                    mediaHolder.mediaPlayer.stop();
                    mediaHolder.mediaPlayer.release();
                    mediaHolder.playListener.onRelease();
                }
            }
            mMediaPlayerMap.remove(tag);
        }
        stopTimer();
    }

    /**
     * 释放所有除了给定key以外的其他的播放
     */
    public void releaseByTagExceptKey(String tag,String key) {
        if(mMediaPlayerMap!=null && mMediaPlayerMap.get(tag)!=null){
            for (Iterator<Map.Entry<String,MediaHolder>> it = mMediaPlayerMap.get(tag).entrySet().iterator();it.hasNext();) {
                Map.Entry<String,MediaHolder> entry = it.next();
                if(entry.getKey()!=null && !entry.getKey().equals(key)){
                    if(entry.getValue()!=null && entry.getValue().mediaPlayer!=null && entry.getValue().playListener!=null){
                        entry.getValue().mediaPlayer.stop();
                        entry.getValue().mediaPlayer.release();
                        entry.getValue().playListener.onPause();
                        entry.getValue().playListener.onRelease();
                        it.remove();
                    }
                }
            }
        }
        stopTimer();
    }

//    /**
//     * 暂停播放
//     * @param key
//     */
//    public void pause(String key){
//        if (isPlayerNotNull(key) && mMediaPlayerMap.get(key).mediaPlayer.isPlaying()) {
//            mMediaPlayerMap.get(key).mediaPlayer.pause();
//        }
//    }


    /**
     * 滑动播放到某个位置
     **/
    public void seekTo(String tag,String key,int position) {
        if (isPlayerNotNull(tag,key)) {
            mMediaPlayerMap.get(tag).get(key).mediaPlayer.seekTo(position);
        }
    }

    /**
     * 是否正在播放
     **/
    public boolean isPlaying(String tag,String key) {
        if (isPlayerNotNull(tag,key)) {
            return mMediaPlayerMap.get(tag).get(key).mediaPlayer.isPlaying();
        }
        return false;
    }

    /**
     * pos = -1 则不跳转到指定位置
     *
     * @param tag
     * @param key
     * @param url
     * @param listener
     * @param pos
     */
    public void startPlay(String tag, String key, String url, AudioPlayListener listener, int pos) {
        if (TextUtils.isEmpty(tag)) {
            ToastUtils.show("tag不可以为空");
            return;
        }
        if (TextUtils.isEmpty(key)) {
            ToastUtils.show("key不可以为空");
            return;
        }
        if (TextUtils.isEmpty(url)) {
            ToastUtils.show("url不可以为空");
            return;
        }
        if (listener == null) {
            ToastUtils.show("listener不可以为空");
            return;
        }
        if (!url.endsWith("mp3")) {//url为空,或者非Mp3格式,则提示return,此校检只在此处做一次,后面其他地方都不用检查
            ToastUtils.show("此链接非mp3格式,不支持");
            return;
        }

        MediaHolder mediaHolder = null;
        if (mMediaPlayerMap.get(tag) != null && mMediaPlayerMap.get(tag).get(key) != null) {
            mediaHolder = mMediaPlayerMap.get(tag).get(key);
        }
        //播放逻辑,没有播放过的,则创建,然后直接播放
        if (mediaHolder == null) {//缓存的mediaPlayer为空则创建
            //避免切换列表音频时的进度回跳
            if(pos!=-1){
                listener.onPositionChanged(pos);
            }
            //暂停其他所有的
            pauseAll();
            mediaHolder = new MediaHolder(newMediaPlayer(listener, pos), listener);
            addMediaPlayer(tag, key, mediaHolder);
            loadMedia(url, mediaHolder);
        } else {
            //正在播放的,如果pos==-1则暂停播放,否则调整位置
            //未正在播放的,如果pos==-1.则开始从头播放,否则从pos位置开始播放
            if (mediaHolder.mediaPlayer.isPlaying()) {
                if (pos == -1) {//正在播放中重复点击播放,则暂停
                    mediaHolder.playListener.onPause();
                    mediaHolder.mediaPlayer.pause();
                } else {//播放中改变播放位置
                    if (mediaHolder.mediaPlayer.getDuration() >= pos) {
                        mediaHolder.playListener.onPositionChanged(pos);
                        mediaHolder.mediaPlayer.seekTo(pos);
                        mediaHolder.playListener.onPlaying();
                    }
                }
            } else {
                if (pos == -1) {//没有播放点击开始播放
                    pauseAll();
                    mediaHolder.mediaPlayer.start();
                    mediaHolder.playListener.onPlaying();
                } else {//没有播放状态下改变位置
                    mediaHolder.playListener.onPositionChanged(pos);
                    pauseAll();
                    mediaHolder.mediaPlayer.seekTo(pos);
                    mediaHolder.mediaPlayer.start();
                    mediaHolder.playListener.onPlaying();
                }
            }
        }
        //每次start时检测一下是否进度更新timer
        startTimer();
    }

    /**
     * 提前加载数据获取一下音频时长,用于服务器无法给出音频时长的情况.
     *
     * @param url
     * @param listener
     */
    public void pendPlay(String url, AudioPlayListener listener) {
        if (TextUtils.isEmpty(url)) {
            return;
        }
        if (listener == null) {
            return;
        }
        if (!url.endsWith("mp3")) {
            return;
        }

        try {
            IjkMediaPlayer mMediaPlayer = new IjkMediaPlayer();
            mMediaPlayer.setDataSource(url);
            mMediaPlayer.setOnPreparedListener(player -> {
                player.setKeepInBackground(false);
                player.setAudioStreamType(AudioManager.STREAM_MUSIC);
                listener.allTimeInit(player.getDuration());
                mMediaPlayer.pause();
                mMediaPlayer.stop();
                mMediaPlayer.release();
            });
            mMediaPlayer.prepareAsync();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void getMp3Length(String url,AudioLength audioLength){
        //解决低版本手机不支持使用此库获取音频时间的问题(低版本调用内部api file.toPath时会崩溃)
        if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.O){
            RxJavaManager.rxJavaRun(new RxJavaCallBack<Integer>() {
                @Override
                public Integer onExecute() {
                    try {
                        MP3File file = new MP3File(url);
                        MP3AudioHeader audioHeader = (MP3AudioHeader) file.getAudioHeader();
                        return audioHeader.getTrackLength();
                    } catch (Exception e) {
                        e.printStackTrace();
                        return -1;
                    }
                }

                @Override
                public void onExecuteFinish(Integer integer) {
                    audioLength.onTimeFetch(integer);
                }
            });
        }else{
            audioLength.onTimeFetch(-1);
        }
    }

    /**
     * 创建,并初始化MediaPlayer
     *
     * @return
     */
    private IjkMediaPlayer newMediaPlayer(AudioPlayListener listener, int pos) {
        IjkMediaPlayer mMediaPlayer = new IjkMediaPlayer();
        //注册,播放完成后的监听
        mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);
        mMediaPlayer.setOnCompletionListener(iMediaPlayer -> {
            Log.d(TAG, "onCompletion");
            listener.onCompletion(iMediaPlayer.getDuration());
        });
//        mMediaPlayer.setOnSeekCompleteListener(new IMediaPlayer.OnSeekCompleteListener(){
//            @Override
//            public void onSeekComplete(IMediaPlayer iMediaPlayer) {
//                iMediaPlayer.start();
//            }
//        });
        mMediaPlayer.setOnInfoListener((iMediaPlayer, i, i1) -> false);
        //不能用这种方式进行进度调整,
//        mMediaPlayer.setOnSeekCompleteListener(player->{
//            Log.d(TAG, "OnSeekComplete");
//            listener.onPositionChanged(player.getCurrentPosition());
//        });
        //监听媒体流是否装载完成
        mMediaPlayer.setOnPreparedListener(new IjkMediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(IMediaPlayer iMediaPlayer) {
                Log.d(TAG, "onPrepared");
                if (pos != -1 && mMediaPlayer.getDuration() > pos) {
                    mMediaPlayer.seekTo(pos);
                    mMediaPlayer.start();
                }
                listener.onPositionChanged(iMediaPlayer.getCurrentPosition());
                listener.onPrepared();
                listener.onPlaying();
                listener.allTimeInit(iMediaPlayer.getDuration());
            }

        });

        /**
         * @date: 2019/6/21 0021

         * @description:监听媒体错误信息
         **/
        mMediaPlayer.setOnErrorListener(new IjkMediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(IMediaPlayer iMediaPlayer, int what, int extra) {
                listener.onError();
                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;
            }
        });
        return mMediaPlayer;
    }

    /**
     * @date: 2019/6/24 0024
     * @description: 加载媒体资源
     **/
    private void loadMedia(String playUrl, MediaHolder mediaHolder) {
        try {
            mediaHolder.playListener.onPreparing();
            mediaHolder.mediaPlayer.setKeepInBackground(false);
            mediaHolder.mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaHolder.mediaPlayer.setDataSource(playUrl);
            mediaHolder.mediaPlayer.prepareAsync();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 简化AudioPlayListener子类的实现,让子类用哪个实现哪个
     */
    public abstract static class EasyAudioPlayListener implements AudioPlayListener {
        @Override
        public void onPreparing() {
        }

        @Override
        public void onPrepared() {
        }

        @Override
        public void onPlaying() {
        }

        @Override
        public void onPositionChanged(long position) {
        }

        @Override
        public void onPause() {
        }

        @Override
        public void onError() {
        }

        @Override
        public void onCompletion(long position) {
        }

        @Override
        public void allTimeInit(long time) {
        }
    }

    public interface AudioPlayListener {
        /**
         * 媒体流加载中
         */
        void onPreparing();

        /**
         * 媒体流加载完成
         */
        void onPrepared();

        /**
         * 播放中
         */
        void onPlaying();

        /**
         * 暂停播放
         */
        void onPause();

        /**
         * 控件释放时调用
         */
        void onRelease();

        /**
         * 播放完成
         */
        void onCompletion(long position);

        /**
         * 播放错误
         */
        void onError();

        /**
         * 播放进度改变
         *
         * @param position
         */
        void onPositionChanged(long position);

        /**
         * 总时长初始化
         *
         * @param position
         */
        void allTimeInit(long position);
    }

    public interface AudioPlayPosition{
        void onPosition(long position);
    }

    /**
     * @date: 2019/6/21 0021
     * @description:开启线程,获取当前播放的进度
     **/
    private void startTimer() {
        if (mDisposable == null) {
            Observable.interval(peridTime, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<Long>() {
                        @Override
                        public void onSubscribe(Disposable disposable) {
                            mDisposable = disposable;
                        }

                        @Override
                        public void onNext(Long number) {
                            notifyPositionChange();
                        }

                        @Override
                        public void onError(Throwable e) {

                        }

                        @Override
                        public void onComplete() {

                        }
                    });
        }
    }

    /**
     * 通知全局正在播放的listener改变当前播放进度
     */
    private void notifyPositionChange() {
        for (HashMap<String, MediaHolder> map : mMediaPlayerMap.values()) {
            for (MediaHolder mediaHolder : map.values()) {
                if (mediaHolder != null && mediaHolder.mediaPlayer != null && mediaHolder.mediaPlayer.isPlaying()) {
                    mediaHolder.playListener.onPositionChanged(mediaHolder.mediaPlayer.getCurrentPosition());
                }
            }
        }
    }

    /**
     * 暂停所有其他的播放
     */
    public void pauseAll() {
        for (HashMap<String, MediaHolder> map : mMediaPlayerMap.values()) {
            for (MediaHolder mediaHolder : map.values()) {
                if (mediaHolder != null && mediaHolder.mediaPlayer != null && mediaHolder.mediaPlayer.isPlaying()) {
                    mediaHolder.mediaPlayer.pause();
                    mediaHolder.playListener.onPause();
                }
            }
        }
        stopTimer();
    }

    /**
     * 暂停所有其他的播放
     */
    public void pauseByTag(String tag) {
        if(mMediaPlayerMap!=null && mMediaPlayerMap.get(tag)!=null){
            for (MediaHolder mediaHolder : mMediaPlayerMap.get(tag).values()) {
                if (mediaHolder != null && mediaHolder.mediaPlayer != null && mediaHolder.mediaPlayer.isPlaying()) {
                    mediaHolder.mediaPlayer.pause();
                    mediaHolder.playListener.onPause();
                }
            }
        }
        stopTimer();
    }

    /**
     * 增加根据tag和url继续播放的方法.
     */
    public void startByTagKey(String tag,String key) {
        if(mMediaPlayerMap!=null && mMediaPlayerMap.get(tag)!=null && mMediaPlayerMap.get(tag).get(key)!=null){
            MediaHolder mediaHolder = mMediaPlayerMap.get(tag).get(key);
            if (mediaHolder != null && mediaHolder.mediaPlayer != null && !mediaHolder.mediaPlayer.isPlaying()) {
                pauseAll();
                mediaHolder.mediaPlayer.start();
                mediaHolder.playListener.onPlaying();
                startTimer();
            }
        }
    }
    /**
     * 增加根据tag和url来判断是否正在播放的方法.
     */
    public boolean isPlayingByTagKey(String tag,String key) {
        if(mMediaPlayerMap!=null && mMediaPlayerMap.get(tag)!=null && mMediaPlayerMap.get(tag).get(key)!=null){
            MediaHolder mediaHolder = mMediaPlayerMap.get(tag).get(key);
            if (mediaHolder != null && mediaHolder.mediaPlayer != null && mediaHolder.mediaPlayer.isPlaying()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 遍历 mMediaPlayerMap 如果没有任何在player正在播放,则停止定时器
     */
    private void stopTimer() {
        if (mMediaPlayerMap.size() > 0) {
            for (HashMap<String, MediaHolder> map : mMediaPlayerMap.values()) {
                for (MediaHolder mediaHolder : map.values()) {
                    if (mediaHolder != null && mediaHolder.mediaPlayer != null && mediaHolder.mediaPlayer.isPlaying()) {//有正在播放的,直接return
                        return;
                    }
                }
            }
            //没有return表示没有正在播放的
            if (mDisposable != null) {
                mDisposable.dispose();
                mDisposable = null;
            }
        }
    }

    private boolean isPlayerNotNull(String tag, String key) {
        return mMediaPlayerMap.get(tag) != null && mMediaPlayerMap.get(tag).get(key) != null && mMediaPlayerMap.get(tag).get(key).mediaPlayer != null;
    }

    /**
     * 保存MediaPlayer 和 listener的数据结构,因为设置定时器回调时间时会需要listener
     */
    private class MediaHolder {
        public IjkMediaPlayer mediaPlayer;
        public AudioPlayListener playListener;

        public MediaHolder(IjkMediaPlayer mediaPlayer, AudioPlayListener playListener) {
            this.mediaPlayer = mediaPlayer;
            this.playListener = playListener;
        }
    }

    public interface AudioLength{
        void onTimeFetch(int length);
    }
}