迷你播放器--第一阶段(3)

MediaPlayer的封装--利用intent实现消息传递

本文章为CSDN作者原创,转载请保留出处:http://blog.csdn.net/lrs0304/article/details/38351181

查看项目源代码请前往:迷你播放器-综述

请注意,该项目为android项目,如果已经学习过这一节请阅读下一篇。

注,封装过程参考了蓝斯的高仿多米 博客为 http://blog.csdn.net/lancees/article/details/7664738

先上效果图(和上一节一样,只是内部架构变了)

本节要处理的问题

  1. 封装Mediaplayer,intent通信,播放状态改变时发送广播
  2. 封装MusicData以使得能够使用bundle发送出去
  3. activity注册于反注册广播(退出时)

1、封装Mediaplayer

怎么说呢,其实封装Mediaplayer就是让它成为一个仅仅是没有界面,但却包含了播放列表,播放模式,支持快进快退上一曲下一曲,能够对外发送状态的一个播放器,这样一来我们就只需要干其他事情了,比如UI,比如解码。封装的一个好处是代码写好以后这个可以直接使用,UI代码出错无须检查这一部分,提高效率。

首先完善MusicPlayState状态的定义()

package com.liangrensheng.music_player.player;public class MusicPlayState {// 播放状态public static final int S_NOFILE = -1; // 无音乐文件public static final int S_INVALID = 0; // 当前音乐文件无效public static final int S_PREPARE = 1; // 准备就绪public static final int S_PLAYING = 2; // 播放中public static final int S_PAUSE = 3; // 暂停// 播放模式public static final int M_SINGLE_LOOP = 0;// 单曲循环public static final int M_LIST_PLAY = 1;// 顺序播放public static final int M_LIST_LOOP = 2;// 循环播放public static final int M_RANDOM = 3;// 随机播放public static final String STATE_NAME = "STATE_NAME";public static final String MUSIC_INDEX = "MUSIC_INDEX";public static final String MUSIC_INVALID = "MUSIC_INVALID";public static final String MUSIC_PREPARE = "MUSIC_PREPARE";public static final String MUSIC_PLAY = "MUSIC_PLAY";public static final String MUSIC_PAUSE = "MUSIC_PAUSE";public static final String MUSIC_STOP = "MUSIC_STOP";// 广播public static final String MUSIC_BROCAST = "liangrensheng.musicplayer.brocast";
}
封装的主体Mediaplayer
package com.liangrensheng.music_player.player;import java.util.ArrayList;
import java.util.List;
import java.util.Random;import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Bundle;public class MusicPlayer implements OnCompletionListener, OnErrorListener {private MediaPlayer mMediaPlayer; // 播放器对象private List<MusicData> mMusicFileList; // 音乐文件列表private int mCurMusicIndex; // 当前播放索引private int mPlayState; // 播放器状态private int mPlayMode; // 歌曲播放模式private Random mRandom;// 产生随机数private Context mContext;//private int wrongMusics;// 循环不超过总数的两倍,预防next播放引起的死循环public MusicPlayer(Context context) {mContext = context;mMediaPlayer = new MediaPlayer();mRandom = new Random();mMusicFileList = new ArrayList<MusicData>();mRandom.setSeed(System.currentTimeMillis());mMediaPlayer.setOnCompletionListener(this);mMediaPlayer.setOnErrorListener(this);DefaultInitial();}/*** 默认配置*/private void DefaultInitial() {mMediaPlayer.reset();mMusicFileList.clear();mCurMusicIndex = -1;mPlayState = MusicPlayState.S_NOFILE;mPlayMode = MusicPlayState.M_LIST_LOOP;// 列表循环wrongMusics = -1;}/*** 退出时重新初始化*/public void exit() {DefaultInitial();// 释放播放器mMediaPlayer.stop();}/*** 更新播放列表*/public void refreshMusicList(List<MusicData> FileList) {if (FileList == null) {mMusicFileList.clear();mPlayState = MusicPlayState.S_NOFILE;mCurMusicIndex = -1;return;} else {mMusicFileList = FileList;if (mMusicFileList.size() == 0) {mPlayState = MusicPlayState.S_NOFILE;mCurMusicIndex = -1;return;}mCurMusicIndex = 0;switch (mPlayState) {case MusicPlayState.S_INVALID:case MusicPlayState.S_NOFILE:case MusicPlayState.S_PREPARE:prepare(mCurMusicIndex);break;default:break;}}}/*** 获取播放列表*/public List<MusicData> getMusicFileList() {return mMusicFileList;}/*** 获取当前播放曲目的序号*/public int getCurIndex() {return mCurMusicIndex;}/*** 获取播放状态*/public int getPlayState() {return mPlayState;}/*** 获取播放模式*/public int getPlayMode() {return mPlayMode;}/*** 设置播放模式*/public void setPlayMode(int mode) {switch (mode) {case MusicPlayState.M_SINGLE_LOOP:case MusicPlayState.M_LIST_PLAY:case MusicPlayState.M_LIST_LOOP:case MusicPlayState.M_RANDOM:mPlayMode = mode;break;}}/*** 播放索引合法化*/private int reviceIndex(int index) {int length = mMusicFileList.size();// 循环播放if (index < 0)index = length - 1;else if (index >= length)index = 0;return index;}/*** 播放进度合法化*/private int reviceSeekValue(int value) {if (value < 0)value = 0;else if (value > 100)value = 100;return value;}/*** 获取随机索引,随机播放使用*/private int getRandomIndex() {int length = mMusicFileList.size();if (length == 0)return -1;elsereturn Math.abs(mRandom.nextInt(length - 1));}/*** 准备资源播放*/private boolean prepare(int index) {mCurMusicIndex = index;if (mMediaPlayer == null)mMediaPlayer = new MediaPlayer();elsemMediaPlayer.reset();String path = mMusicFileList.get(index).mMusicPath;try {mMediaPlayer.setDataSource(path);mMediaPlayer.prepare();// Async();// 异步的,不会阻塞当前UI线程mPlayState = MusicPlayState.S_PREPARE;wrongMusics = -1;} catch (Exception e) {mPlayState = MusicPlayState.S_INVALID;// 非法sendPlayStateBrocast();wrongMusics += 1;if (wrongMusics < 2 * mMusicFileList.size()) {// 统计错误次数playNext();}return false;}sendPlayStateBrocast();return true;}/*** 获取播放器Duration(音乐持续时间)*/public int getDuration() {if (mPlayState == MusicPlayState.S_INVALID|| mPlayState == MusicPlayState.S_NOFILE)return 0;elsereturn mMediaPlayer.getDuration();}/*** 获取播放进度*/public int getCurPosition() {if (mPlayState == MusicPlayState.S_PLAYING|| mPlayState == MusicPlayState.S_PAUSE)return mMediaPlayer.getCurrentPosition();elsereturn 0;}/*** 播放第index首*/public boolean playIndex(int index) {if (mPlayState == MusicPlayState.S_NOFILE)return false;mCurMusicIndex = index;if (prepare(mCurMusicIndex))return play();elsereturn false;}/*** 播放*/public boolean play() {if (mPlayState == MusicPlayState.S_NOFILE|| mPlayState == MusicPlayState.S_INVALID)return false;if (mMediaPlayer == null) {mMediaPlayer = new MediaPlayer();prepare(mCurMusicIndex);}mMediaPlayer.start();mPlayState = MusicPlayState.S_PLAYING;sendPlayStateBrocast();return true;}/*** 暂停*/public boolean pause() {if (mPlayState != MusicPlayState.S_PLAYING)return false;mMediaPlayer.pause();mPlayState = MusicPlayState.S_PAUSE;sendPlayStateBrocast();return true;}/*** 停止*/public boolean stop() {if (mPlayState != MusicPlayState.S_PAUSE&& mPlayState == MusicPlayState.S_PLAYING)return false;elsereturn prepare(mCurMusicIndex);}/*** 上一首*/public boolean playPre() {if (mPlayState == MusicPlayState.S_NOFILE)return false;mCurMusicIndex--;mCurMusicIndex = reviceIndex(mCurMusicIndex);// 合法化if (prepare(mCurMusicIndex))return play();elsereturn false;}/*** 下一首*/public boolean playNext() {if (mPlayState == MusicPlayState.S_NOFILE)return false;if (mPlayMode == MusicPlayState.M_RANDOM) {int index = getRandomIndex();if (index == -1) {mCurMusicIndex++;} elsemCurMusicIndex = index;mCurMusicIndex = reviceIndex(mCurMusicIndex);} else {mCurMusicIndex++;mCurMusicIndex = reviceIndex(mCurMusicIndex);// 合法化}if (prepare(mCurMusicIndex))return play();elsereturn false;}/*** 进度跳转*/public boolean seekTo(int rate) {if (mPlayState == MusicPlayState.S_INVALID|| mPlayState == MusicPlayState.S_NOFILE)return false;rate = reviceSeekValue(rate);int time = mMediaPlayer.getDuration();int curTime = (int) ((float) rate / 100 * time);mMediaPlayer.seekTo(curTime);return true;}/*** 广播播放状态,*/public void sendPlayStateBrocast() {if (mContext != null) {Intent intent = new Intent(MusicPlayState.MUSIC_BROCAST);intent.putExtra(MusicPlayState.STATE_NAME, mPlayState);intent.putExtra(MusicPlayState.MUSIC_INDEX, mCurMusicIndex);if (mPlayState != MusicPlayState.S_NOFILE) {// 将当前音乐的信息广播回去Bundle bundle = new Bundle();MusicData data = mMusicFileList.get(mCurMusicIndex);bundle.putParcelable(MusicData.KEY_MUSIC_DATA, data);intent.putExtra(MusicData.KEY_MUSIC_DATA, bundle);}mContext.sendBroadcast(intent);}}/*** 播放完成时的动作*/@Overridepublic void onCompletion(MediaPlayer mp) {switch (mPlayMode) {case MusicPlayState.M_SINGLE_LOOP:playIndex(mCurMusicIndex);break;case MusicPlayState.M_LIST_PLAY: {if (mCurMusicIndex != mMusicFileList.size() - 1)playNext();elseprepare(mCurMusicIndex);}break;case MusicPlayState.M_LIST_LOOP:playNext();break;case MusicPlayState.M_RANDOM: {int index = getRandomIndex();if (index == -1) {mCurMusicIndex++;} elsemCurMusicIndex = index;mCurMusicIndex = reviceIndex(mCurMusicIndex);if (prepare(mCurMusicIndex))play();}break;default:prepare(mCurMusicIndex);break;}}/*** 播放的时候发生错误*/@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {// System.out.println("矮油,播放出错了哟");return false;}
}

2、封装MusicData

另外,由于我们使用intent形式发送将MusicData,因此这个MusicData必须具有Parcelable属性
package com.liangrensheng.music_player.player;import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;public class MusicData implements Parcelable {public final static String KEY_MUSIC_DATA = "MusicData";private final static String KEY_MUSIC_NAME = "MusicName";private final static String KEY_MUSIC_TIME = "MusicTime";private final static String KEY_MUSIC_PATH = "MusicPath";private final static String KEY_MUSIC_ARITST = "MusicAritst";public String mMusicName;public int mMusicTime;public String mMusicPath;public String mMusicAritst;public MusicData() {mMusicName = "";mMusicTime = 0;mMusicPath = "";mMusicAritst = "";}@Overridepublic int describeContents() {return 0;}/*** implements 了Parcelable,是的该结构能够被发送*/@Overridepublic void writeToParcel(Parcel dest, int flags) {Bundle mBundle = new Bundle();mBundle.putString(KEY_MUSIC_NAME, mMusicName);mBundle.putInt(KEY_MUSIC_TIME, mMusicTime);mBundle.putString(KEY_MUSIC_PATH, mMusicPath);mBundle.putString(KEY_MUSIC_ARITST, mMusicAritst);dest.writeBundle(mBundle);}public static final Parcelable.Creator<MusicData> CREATOR = new Parcelable.Creator<MusicData>() {@Overridepublic MusicData createFromParcel(Parcel source) {MusicData Data = new MusicData();Bundle mBundle = new Bundle();mBundle = source.readBundle();Data.mMusicName = mBundle.getString(KEY_MUSIC_NAME);Data.mMusicTime = mBundle.getInt(KEY_MUSIC_TIME);Data.mMusicPath = mBundle.getString(KEY_MUSIC_PATH);Data.mMusicAritst = mBundle.getString(KEY_MUSIC_ARITST);return Data;}@Overridepublic MusicData[] newArray(int size) {return new MusicData[size];}};
}

3、为了正常接收Mediaplayer的广播,我们还得在activity里注册一下,代码如下,这段到是蛮简单的。但是此次升级改动较多,包括删除了activity里的playIndex以及增加了广播接收器

新建活动时新建musicplayer和注册接收器
        musicPlayer = new MusicPlayer(this);// 初始化播放列表musicPlayer.refreshMusicList(m_MusicFileList);// 注册音乐播放状态接收器mPlayStateBrocast = new MusicPlayStateBrocast();IntentFilter intentFilter1 = new IntentFilter();intentFilter1.addAction(MusicPlayState.MUSIC_BROCAST);registerReceiver(mPlayStateBrocast, intentFilter1);
在销毁活动时反注册
    @Overrideprotected void onDestroy() {unregisterReceiver(mPlayStateBrocast);// 取消注册android.os.Process.killProcess(android.os.Process.myPid());}
接收器的具体内容
    /*** 用于接收musicPlayer发过来的广播,更新UI控件*/class MusicPlayStateBrocast extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (action.equals(MusicPlayState.MUSIC_BROCAST)) {updatePlayState(intent);}}/*** 更新音乐状态,当前播放音乐名称,根据接收到的广播* * @param intent*/private void updatePlayState(Intent intent) {MusicData data = new MusicData();int state = intent.getIntExtra(MusicPlayState.STATE_NAME, -1);Bundle bundle = intent.getBundleExtra(MusicData.KEY_MUSIC_DATA);if (bundle != null) {data = bundle.getParcelable(MusicData.KEY_MUSIC_DATA);}int playIndex = intent.getIntExtra(MusicPlayState.MUSIC_INDEX, -1);if (data != null) {mListViewAdapter.setPlayState(playIndex, state);String musicInfo = data.mMusicName + " - " + data.mMusicAritst;musicName.setText(musicInfo + "            ");}switch (state) {case MusicPlayState.S_INVALID: {// 无效音乐musicName.setText(data.mMusicName + " 无效或权限不足");mListViewAdapter.setPlayState(playIndex, MusicPlayState.S_PAUSE);playState.setBackgroundResource(R.drawable.state_pause);musicName.setEllipsize(TruncateAt.END);}break;case MusicPlayState.S_PAUSE: {// 暂停mListViewAdapter.setPlayState(playIndex, MusicPlayState.S_PAUSE);playState.setBackgroundResource(R.drawable.state_pause);musicName.setEllipsize(TruncateAt.END);}break;case MusicPlayState.S_PLAYING: {// 播放musicName.setEllipsize(TruncateAt.MARQUEE);mListViewAdapter.setPlayState(playIndex,MusicPlayState.S_PLAYING);playState.setBackgroundResource(R.drawable.state_play);}break;case MusicPlayState.S_PREPARE: {// 正在准备mListViewAdapter.setPlayState(playIndex, MusicPlayState.S_PAUSE);playState.setBackgroundResource(R.drawable.state_pause);musicName.setEllipsize(TruncateAt.END);}break;default:break;}}}
本小节源代码下载 : http://download.csdn.net/detail/lrs0304/7730235

迷你播放器--第一阶段(3)--MediaPlayer的封装相关推荐

  1. 迷你播放器--第一阶段(1)--检索媒体音乐并添加到List播放列表

    迷你播放器--第一阶段(1) 检索音乐并添加到List播放列表--媒体库的检索以及list列表使用 本文章为CSDN作者原创,转载请保留出处:http://blog.csdn.net/lrs0304/ ...

  2. 迷你播放器--第一阶段(7)--安全攻防第一战--对抗反编译,代码混淆和对抗动态调试

    迷你播放器--第一阶段(7) 安全攻防第一战--对抗反编译,代码混淆和对抗动态调试; 本文章为CSDN作者原创,转载请保留出处:http://blog.csdn.net/lrs0304/article ...

  3. 迷你播放器--第一阶段(6)--添加搜索定位功能(进阶)-使用filter过滤以及对汉语拼音的排序匹配

    迷你播放器--第一阶段(6) 添加搜索定位功能(进阶)-使用filter过滤以及对汉语拼音的排序匹配; 本文章为CSDN作者原创,转载请保留出处:http://blog.csdn.net/lrs030 ...

  4. 迷你播放器--第一阶段(5)--添加搜索功能--autoCompleteBox的使用

    迷你播放器--第一阶段(5) 添加搜索功能--autoCompleteBox的使用; 本文章为CSDN作者原创,转载请保留出处:http://blog.csdn.net/lrs0304/article ...

  5. 迷你播放器--第一阶段(2)--退出时自动最小化(不是关闭),增加当前播放曲目的跑马灯效果

    迷你播放器--第一阶段(2) 退出时自动最小化(不是关闭),增加当前播放曲目的跑马灯效果 本文章为CSDN作者原创,转载请保留出处:http://blog.csdn.net/lrs0304/artic ...

  6. 迷你播放器--第一阶段(4)--内存卡检索不到音乐的错误处理--程序内部空间管理

    迷你播放器--第一阶段(4) 内存卡检索不到音乐的错误处理--程序内部空间管理 本文章为CSDN作者原创,转载请保留出处:http://blog.csdn.net/lrs0304/article/de ...

  7. Android MediaPlayer MP3播放器(倍速和音量)的封装和所见的问题

    Android MediaPlayer MP3播放器(倍速和音量)的封装和所见的问题 文章目录 Android MediaPlayer MP3播放器(倍速和音量)的封装和所见的问题 一.技术选型 二. ...

  8. 做一个迷你播放器放在桌面

    效果如图 功能 随意选取歌曲,循环播放,有音谱效果,音量控制,显示歌曲名,歌曲控制(播放与暂停.下一首和上一首) 操作 将下面文件下载解压后放在MP3音乐文件夹内(该文件用FLASHPACKER打包) ...

  9. (十八)用JAVA编写MP3解码器——迷你播放器

    2019独角兽企业重金招聘Python工程师标准>>> 1.定义解码一帧的接口   ILayer123 Layer1.Layer2和Layer3这三个类都实现了ILayer123的d ...

最新文章

  1. python import io_详解Python IO编程
  2. 手机直播系统源码搭建说明
  3. Linux课程---11、Linux中软件安装和调试
  4. 20180716:开博宣言
  5. numeric column can contains null
  6. 阿里云移动端播放器高级功能---安全播放
  7. 2020数字营销白皮书
  8. 成年人才是走失比例最高的!今日头条发布走失人口数据报告
  9. android wine教程_技术|如何在 Android 上借助 Wine 来运行 Windows Apps
  10. APP自动化测试系列之appium-desktop配置及录制脚本
  11. Server.UrlEncode、HttpUtility.UrlDecode的区别
  12. python网盘开发_python实现网盘自动化操作(GUI版)
  13. wms仓库管理系统具有四大功能
  14. python爬贴吧回复内容_Python爬虫_获取贴吧内容
  15. KaLi Linux 2019.2安装netspeed
  16. java全套学习课程
  17. java 简单的聊天室_Java简单聊天室
  18. supper的常见错误
  19. sw运行很卡怎么办_怎样才能提高Solidworks的运行速度/SW运行慢怎么办?
  20. 劝大家别去国企制造业干IT,软件多数据乱,报表开发完全没法做

热门文章

  1. 由于找不到libmysql.dIl, 无法继续执行代码。重新安装程序可能会解决此问题
  2. 30 行代码实现蚂蚁森林自动偷能量
  3. PLX PCIe Switch使用
  4. 鼠标在用了一段之后偶然发现以给特别慢的速度移动鼠标,会在移动到可点击的选项按钮附近明显的卡住问题。
  5. 给图片加水印的简单方法,手机图片加水印也可以用
  6. 在GridControl中使用GridLookUpEdit的正确姿势
  7. 图形学/OpenGL/3D数学/Unity
  8. python: xlsx表格转为csv文件
  9. Android开发是简单的「能写应用就行」吗?复习指南
  10. 如何使用git 生成密钥?