Android|Android MediaPlayer的封装

注意 本文封装是在android音视频指南-MediaPlayer概述上进行的2次开发。二次封装完成后,我提供了正在播放、暂停播放、重置、播放完成、媒体流装载完成、媒体流加载中、异常错误等的状态返回
业务需求 需要对音乐媒体类进行播放,如果需要播放的音乐本地缓存没有,需要先下载,然后加载音乐。如果有本地缓存的音乐,直接从本地缓存里面读取,然后加载最后播放
使用说明 1、你需要在自己的Activity或者Fragment去 implements PlaybackInfoListener 接口

MediaPlayerHolder mediaPlayerIngHolder = new MediaPlayerHolder(); mediaPlayerIngHolder.setmPlaybackInfoListener(this); //设置监听

【Android|Android MediaPlayer的封装】2、如果是要加载网络音乐(我建议先下载下来),或者是本地音乐,需要调用
mediaPlayerIngHolder.loadMedia(path); //加载音乐,不是属于播放的状态 mediaPlayerIngHolder.play(); //开始播放,注意:需要等到onStateChanged == PLAYSTATUS4才可以调用这个方法

3、如果不需要播放了,需要释放资源
mediaPlayerIngHolder.release(); mediaPlayerIngHolder = null;

接口回调说明
void onTotalDuration(int duration); //返回音乐的总时长 void onPositionChanged(int position); //当播放的进度 void onStateChanged(int state); //记录当前的状态 void onPlaybackCompleted(); //播放完成回调

学习总结 1、每次调用mediaPlayerIngHolder.loadMedia方法,都需要 mMediaPlayer.reset(),这样是防止再次添加进来出现崩溃信息
2、为了避免阻塞主线程,预加载音乐需要使用mMediaPlayer.prepareAsync(); 预加载完成才可以使用mMediaPlayer.start(); 播放音乐
代码展示
/** * @date: 2019/6/21 0021 * @author: gaoxiaoxiong * @description:播放回调 **/ public interface PlaybackInfoListener { void onTotalDuration(int duration); //总时长void onPositionChanged(int position); //当前时长进度void onStateChanged(int state); //记录当前的状态void onPlaybackCompleted(); //播放完成回调 }

public interface PlayerAdapterListener { void loadMedia(String musiUrl); //加载媒体资源void release(); //释放资源boolean isPlaying(); //判断是否在播放void play(); //开始播放void reset(); //重置void pause(); //暂停void medisaPreparedCompled(); //完成媒体流的装载void seekTo(int position); //滑动到某个位置 }

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; //错误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; //音乐地址,可以是本地的音乐,可以是网络的音乐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(); //注册,播放完成后的监听 mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mediaPlayer) { stopUpdatingCallbackWithPosition(true); if (mPlaybackInfoListener != null) { mPlaybackInfoListener.onStateChanged(PLAYSTATUS3); mPlaybackInfoListener.onPlaybackCompleted(); } } }); //监听媒体流是否装载完成 mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { medisaPreparedCompled(); } }); /** * @date: 2019/6/21 0021 * @author: gaoxiaoxiong * @description:监听媒体错误信息 **/ 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(); //防止再次添加进来出现崩溃信息 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:开启线程,获取当前播放的进度 **/ 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:更新当前的进度 **/ 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:加载完成回调 **/ @Override public void medisaPreparedCompled() { int duration = mMediaPlayer.getDuration(); //获取总时长 if (mPlaybackInfoListener != null) { mPlaybackInfoListener.onTotalDuration(duration); mPlaybackInfoListener.onPositionChanged(0); mPlaybackInfoListener.onStateChanged(PLAYSTATUS4); } }/** * @date: 2019/6/21 0021 * @author: gaoxiaoxiong * @description:滑动播放到某个位置 **/ @Override public void seekTo(int position) { if (mMediaPlayer != null) { mMediaPlayer.seekTo(position); } }/** * @date: 2019/6/21 0021 * @author: gaoxiaoxiong * @description:播放完成回调监听 **/ private void stopUpdatingCallbackWithPosition(boolean resetUIPlaybackPosition) { if (mExecutor != null) { mExecutor.shutdownNow(); mExecutor = null; mSeekbarPositionUpdateTask = null; if (resetUIPlaybackPosition && mPlaybackInfoListener != null) { mPlaybackInfoListener.onPositionChanged(0); } } } }

    推荐阅读