仅仅记录自己的学习记录,错误之处欢迎指出。
效果图:
对android音频播放器都不陌生了,使用MediaPlayer可以播放mp3文件,也可以循环或者重复播放一个列表的文件,和市场上面的一些播放器一样。直接看源码+注释
布局文件activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/start"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/back"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/next"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/pause"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/continuePlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/stop"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
这个就不解释了,只是几个按钮
然后看一下管理类,用来对音频播放进行管理,可以上一首,下一首,暂停,继续,播放等等的操作:
public class PlayManager {
private static PlayManager pManager = null; // 单例
private String[] playStatus = { "end of music list", "top of music list",
"play" }; // 播放状态
private MediaPlayer mediaPlayer = null; // 播放工具类,系统类
private String[] fileArray = null; // 播放文件的路径数组,相当于文件列表
private int playPostition = 0; // 当前播放文件的位置,可用于暂停和继续播放的
private int currentFilePosition = -1; // 当前播放的是第几个文件
public static PlayManager getInstance() {
if (pManager == null) {
pManager = new PlayManager();
}
return pManager;
}
private PlayManager() { // 在该管理类初始化时,就读取MainActivity.URL下的文件,找出mp3文件
// 这里是将路径写在代码里面了,你也可以将它写在一个文件夹浏览处,这样就可以动态的改变路径了
fileArray = getFileArray(MainActivity.URL);
}
private String[] getFileArray(String url) { // 得到MainActivity.URL下的mp3文件
String[] s = new File(url).list();
if (s == null || s.length == 0) { // 若MainActivity.URL下面没有文件,则直接返回
return null;
}
int length = s.length;
List<String> list = new ArrayList<String>(); // new一个集合,只存放mp3文件的路径
for (int i = 0; i < length; i++) {
if (s[i].endsWith(".mp3")) {
list.add(s[i]);
}
}
int listSize = list.size();
if (listSize == 0) {
return null;
}
String[] res = new String[listSize]; // 将mp3文件路径赋给字符串数组,然后返回它
for (int i = 0; i < listSize; i++) {
res[i] = url + list.get(i);
MainActivity.LogI (res[i]);
}
return res;
}
public String startPlayVideo() throws Exception { // 开始播放
currentFilePosition = 0; // 因为currentFilePosition的初始值是-1,所以此处强制赋值为0,即播放第一个音频文件,返回播放状态
return playMusic();
}
private String playMusic() throws Exception {
if (currentFilePosition >= fileArray.length) { // 首先判断当前播放的文件是否超多了列表
return playStatus[0]; // 返回到低了,你也可以直接写成currentFilePosition=0,这样就能循环播放列表了
}
if (currentFilePosition < 0) {
return playStatus[1]; // 返回到顶了,你也可以写成currentFilePosition=fileArray.length,这样反过来循环播放列表
}
releaseMedia(); // 每次开始播放列表时,都要将mediaPlayer释放掉,这样一边准备下一首或者上一首
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(fileArray[currentFilePosition]); // 设置播放文件的路径
MainActivity.LogI("this file's path is "
+ fileArray[currentFilePosition]);
mediaPlayer.prepare(); // 准备
mediaPlayer.start(); // 开始播放
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
try {
playNextMusic(); // 在每次播放完成之后都用播放下一首
MainActivity.LogI("completion this music, play the next");
} catch (Exception e) {
e.printStackTrace();
}
}
});
return playStatus[2]; // 返回正在播放
}
public String playNextMusic() throws Exception {
currentFilePosition++; // 播放下一首时当前播放文件加1
return playMusic();
}
public String playBackMusic() throws Exception {
currentFilePosition--; // 减1,播放上一首
return playMusic();
}
public void pausePlayMusic() { // 暂停
if (mediaPlayer != null) {
playPostition = mediaPlayer.getCurrentPosition(); // 得到当前播放的位置
mediaPlayer.pause();
}
}
public void continuePlay() { // 继续
if (mediaPlayer != null) {
mediaPlayer.seekTo(playPostition); // 从记录的位置开始播放
mediaPlayer.start();
}
}
public void stopPlay() {
if (mediaPlayer != null) { // 停止播放器
mediaPlayer.stop();
}
}
public void releaseMedia() { // 这里是释放mediaPlayer播放对象
if (mediaPlayer != null) {
try {
mediaPlayer.release();
mediaPlayer = null;
System.gc();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
上面的注解已经很清晰了,到这里基本上就能完全控制音频的播放了,当然你也可以增加几个按钮用来快进和快退,快进就是将playPostition增加一定的量,快退就是将playPostition减少一定的量。
下面再来看看界面类MainActivity
public class MainActivity extends Activity {
public static String URL = "mnt/sdcard/"; // 音频文件所在路径
private static String TAG = "zyj"; // 调试
private static boolean toast = true;
private static boolean debug = true;
private static MainActivity mActivity = null;
private Button start = null;
private Button pause = null;
private Button continuePlay = null;
private Button stop = null;
private Button next = null;
private Button back = null;
private MyListener listener = new MyListener();
private PlayManager pManager = PlayManager.getInstance(); // 得到管理类实例
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mActivity = this;
initView();
}
private void initView() { // 初始化全部的按钮,并设置监听
start = (Button) findViewById(R.id.start);
start.setText("start");
start.setOnClickListener(listener);
pause = (Button) findViewById(R.id.pause);
pause.setText("pause");
pause.setOnClickListener(listener);
continuePlay = (Button) findViewById(R.id.continuePlay);
continuePlay.setText("continuePlay");
continuePlay.setOnClickListener(listener);
stop = (Button) findViewById(R.id.stop);
stop.setText("stop");
stop.setOnClickListener(listener);
next = (Button) findViewById(R.id.next);
next.setText("next");
next.setOnClickListener(listener);
back = (Button) findViewById(R.id.back);
back.setText("back");
back.setOnClickListener(listener);
}
public class MyListener implements OnClickListener {
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:
try {
toastMsg(pManager.startPlayVideo()); // 在界面上显示点击之后播放状态
start.setOnClickListener(null); // 点击开始之后,然按钮失效
} catch (Exception e) {
e.printStackTrace();
}
break;
case R.id.back:
try {
toastMsg(pManager.playBackMusic()); // 上一首
} catch (Exception e) {
e.printStackTrace();
}
break;
case R.id.next: // 下一首
try {
toastMsg(pManager.playNextMusic());
} catch (Exception e) {
e.printStackTrace();
}
break;
case R.id.pause: // 暂停
pManager.pausePlayMusic();
break;
case R.id.continuePlay: // 继续
pManager.continuePlay();
break;
case R.id.stop: // 直接停止
pManager.stopPlay();
start.setOnClickListener(listener); // 停止之后让开始按钮起作用
break;
}
}
}
protected void onDestroy() {
super.onDestroy();
pManager.releaseMedia(); // 在销毁方法里对播放器进行释放
}
public static void LogI(String msg) {
if (debug) {
Log.i(TAG, msg);
}
}
public static void toastMsg(String msg) {
if (toast) {
Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show();
}
}
}
到此就基本结束了
另外需要说明几点的是:
*加载MediaPlayer时,有两种方式,第一种是利用静态方法,MediaPlayer.create(...)方式来得到一个MediaPlayer实例,这个方法每次都会返回一个MediaPlayer实例对象,如果程序需要使用MediaPlayer循环播放多个音频文件,此方法就不太合适了
*第二种方式,直接new一个MediaPlayer实例,然后通过setDataSource(...)方法来设置文件路径,注:当调用setDataSource方法之后,MediaPlayer并不会真正的去加载音频文件,而是需要调用MediaPlayer中的prepare方法准备音频,所谓的“准备”,也就是让MediaPlayer真正的去加载音频文件