一、音乐播放器界面截图,录屏
模拟器
手机(测试中发现部分机型有闪退情况,截图展示的手机型号为荣耀9)
手机录屏
https://www.bilibili.com/video/av39894045/
二、功能代码
该音乐播放器实现的功能有,播放,暂停,停止,切换上一首,下一首,扫描手机内存所有目录下的所有音乐文件,时间进度条显示,拖动进度条快进快退,下面依次展示这几个部分的代码:
(1)播放暂停功能(使用同一个按钮,按下暂停改变为播放按钮,按下播放改变为暂停按钮)
//播放暂停
final ImageButton pause = (ImageButton) findViewById(R.id.pause);
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!music_path.isEmpty()) { // 如果已经点击了列表中的某个音乐,音乐路径是指定的
mediaPlayer.start(); //播放
isStop = false;
pause.setImageResource(android.R.drawable.ic_media_pause); // 播放按钮和暂停按钮变换
}
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause(); //暂停
isStop = true;
pause.setImageResource(android.R.drawable.ic_media_play);
}
if (music_path.isEmpty()) // 如果一开始没有点击列表选择音乐,音乐路径是空的,这时候需要给一个提示
Toast.makeText(getApplicationContext(), "点击音乐即可播放", Toast.LENGTH_SHORT).show();
}
});
(2)停止播放功能
// 停止播放
final ImageButton stop = (ImageButton)findViewById(R.id.stop);
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mediaPlayer.reset(); // 停止播放
isStop = true;
}
});
(3)切换上一首和下一首功能
//切换上一曲和下一曲
final ImageButton previous = (ImageButton) findViewById(R.id.previous);
previous.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
music_index--;
changeMusic(music_index); // 调用changeMusic方法
pause.setImageResource(android.R.drawable.ic_media_pause);// 因为切歌后就开始播放了,所以播放暂停按钮要置为暂停的图标
}
});
final ImageButton next = (ImageButton) findViewById(R.id.next);
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
music_index++;
changeMusic(music_index);
pause.setImageResource(android.R.drawable.ic_media_pause);
}
});
}
// changeMusic方法用于切换音乐
private void changeMusic(int index) {
if (index < 0) { // 处理边界问题
music_index = index = list.size() - 1;
} else if (index > list.size() - 1) {
music_index = index = 0;
}
music_path = MusicPath[index]; // 获取音乐文件的路经
try {
mediaPlayer.reset(); // 切歌之前先重置,释放掉之前的资源
mediaPlayer.setDataSource(music_path); // 指定音频文件路径
mediaPlayer.prepare(); // 让mediaPlayer进入准备状态
mediaPlayer.start(); // 开始播放
} catch (IOException e) {
e.printStackTrace();
}
seekBar.setProgress(0); //将进度条初始化
seekBar.setMax(mediaPlayer.getDuration());//设置进度条最大值为音乐总时间
totalTime.setText(formatTime(mediaPlayer.getDuration())); //显示音乐总时长
updateProgress();//更新进度条
}
(4)扫描所有音乐文件,生成音乐列表并显示
private String []MusicName = new String[100]; // 音乐文件名数组
private String []MusicPath = new String[100]; // 音乐文件路径数组
// 生成音乐列表
list = new ArrayList<String>();
try {
Context context = this;
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null ,
null , null , MediaStore.Audio.Media.DEFAULT_SORT_ORDER); // 使用系统提供的数据库查询接口,使用query方法查询所有音频文件
int i = 0;
if(cursor != null){
while (cursor.moveToNext()){
MusicName[i] = new String(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME))); // 获取音乐文件名
MusicPath[i] = new String(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA))); // 获取音乐文件路径
i = i + 1;
}
}
}catch (Exception e){
Toast.makeText(getApplicationContext(), "获取音乐失败", Toast.LENGTH_SHORT).show();;
}
int i = 0;
while(MusicName[i] != null){
list.add(MusicName[i]); // 将文件名写入列表
i++;
}
// 设置ListView样式
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_single_choice,
list);
ListView li = (ListView) findViewById(R.id.listView1);
li.setAdapter(adapter);
li.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
(5)时间进度条显示功能
private SeekBar seekBar; // 时间进度条组件
private TextView currentTime; // 播放当前时间
private TextView totalTime; // 音乐的总时间
private Timer timer; // 定时器
// 用于实现进度条更新的Handler
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message message) {
// 展示进度条和当前时间
int progress = mediaPlayer.getCurrentPosition();
seekBar.setProgress(progress);
currentTime.setText(formatTime(progress));
// 定时发送数据
updateProgress();
return true;
}
});
private void updateProgress() {
// 使用Handler每间隔1s发送一次消息,通知进度条更新
Message msg = Message.obtain();
// 用当前播放时间除以总时间获取播放进度
int progress = mediaPlayer.getCurrentPosition();
msg.arg1 = progress;
mHandler.sendMessageDelayed(msg, 1000);
}
//formatTime方法用于对时间进行格式化,形式是mm:ss
private String formatTime(int length) {
Date date = new Date(length);
SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
String totalTime = sdf.format(date);
return totalTime;
}
(6)拖动进度条快进快退功能
seekBar.setOnSeekBarChangeListener(new MoveSeekBar());
private boolean isSeekBarChanging; //判断是否在滑动进度条,这个时候定时器是停止的
// 滑动进度条
public class MoveSeekBar implements SeekBar.OnSeekBarChangeListener {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
//滑动时,应当暂停后台定时器
public void onStartTrackingTouch(SeekBar seekBar) {
isSeekBarChanging = true;
}
//滑动结束后,重新设置值
public void onStopTrackingTouch(SeekBar seekBar) {
isSeekBarChanging = false;
mediaPlayer.seekTo(seekBar.getProgress());
}
}
三、coding链接
https://git.dev.tencent.com/ysh1998/MusicPlayer.git
四、apk链接
https://dev.tencent.com/u/ysh1998/p/MusicPlayer/git/blob/master/app/app-release.apk