本博客作为作业展示
音乐播放器
基本功能
- 获取本地音乐并展示在列表中
- 播放,暂停,上一首以及下一首
- 点击列表中的音乐来直接播放
界面
说明:上半部分显示列表(androidx.recyclerview.widget.RecyclerView),下半部分(RelativeLayout)显示播放器状态(TextView×3),歌曲名称,歌手信息,上/下一首以及播放暂停键(Button×3)
说明:左边为歌曲序号(TextView×4),右边从上至下依次为歌曲名称,歌手,以及时长
代码方面
创建音乐类
每首歌都有id,歌曲名称,歌手,进度,以及路径(因为要播放)
public class LocalMusicBean {
private String id;
private String song;
private String singer;
private String duration;
private String path;
//并创建全参构造器,在此省略
}
列表显示(创建Adapter)
绑定数据并设置点击事件
Context context;
List<LocalMusicBean>mDatas;
OnItemClickListener onItemClickListener;
public void SetOnItemClickListener(OnItemClickListener onItemClickListener)
{
this.onItemClickListener=onItemClickListener;
}
public interface OnItemClickListener{
public void OnItemClick(View v,int position);
}
public LocalMusic(Context context, List<LocalMusicBean> mDatas) {
this.context = context;
this.mDatas = mDatas;
}
class LocalMusicViewHolder extends RecyclerView.ViewHolder{
TextView id,song,singer,duration;
public LocalMusicViewHolder(@NonNull View itemView) {
super(itemView);
id=itemView.findViewById(R.id.item_local_music_num);
song=itemView.findViewById(R.id.item_local_music_songname);
singer=itemView.findViewById(R.id.item_local_music_singer);
duration=itemView.findViewById(R.id.item_local_music_duration);
}
}
public void onBindViewHolder(@NonNull LocalMusicViewHolder holder, int position) {
LocalMusicBean localMusicBean = mDatas.get(position);
holder.id.setText(localMusicBean.getId());
holder.song.setText(localMusicBean.getSong());
holder.singer.setText(localMusicBean.getSinger());
holder.duration.setText(localMusicBean.getDuration());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.OnItemClick(v,position);
}
});
}
@Override
public LocalMusicViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(context).inflate(R.layout.item_music,parent,false);
LocalMusicViewHolder localMusicViewHolder = new LocalMusicViewHolder(view);
return localMusicViewHolder;
}
MainActivity
设置每一项点击事件
private void setEventListener() {
adapter.SetOnItemClickListener(new LocalMusic.OnItemClickListener() {
@Override
public void OnItemClick(View v, int position) {
currentPlayStation=position;
LocalMusicBean musicBean=mDatas.get(position);
playMusicPosition(musicBean);
}
});
}
切换音乐
private void playMusicPosition(LocalMusicBean musicBean) {
tbxsinger.setText(musicBean.getSinger());
tbxsongs.setText(musicBean.getSong());
stopMusic();
mediaPlayer.reset();
try {
tbxtips.setText("正在播放:");
mediaPlayer.setDataSource(musicBean.getPath());
playMusic();
} catch (IOException e) {
e.printStackTrace();
}
}
暂停播放
private void pauseMusic() {
if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {
currentPause=mediaPlayer.getCurrentPosition();
mediaPlayer.pause();
btnstart.setText(">");
}
}
开始播放音乐
private void playMusic() {
if (mediaPlayer!=null&&!mediaPlayer.isPlaying()) {
if (currentPause==0) {
try {
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}else {
mediaPlayer.seekTo(currentPause);
mediaPlayer.start();
}
btnstart.setText("||");
}
}
停止音乐
private void stopMusic() {
if (mediaPlayer!=null)
{
mediaPlayer.pause();
mediaPlayer.seekTo(0);
mediaPlayer.stop();
btnstart.setText(">");
currentPause=0;
}
}
获取本地音乐
private void LoadLocalMusicData() {
ContentResolver contentResolver = getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor query = contentResolver.query(uri, null, null, null, null);
int id=0;
while (query.moveToNext())
{
String song= query.getString(query.getColumnIndex(MediaStore.Audio.Media.TITLE));
String singer=query.getString(query.getColumnIndex(MediaStore.Audio.Media.ARTIST));
id++;
String sid= String.valueOf(id);
String path=query.getString(query.getColumnIndex(MediaStore.Audio.Media.DATA));
long aLong = query.getLong(query.getColumnIndex(MediaStore.Audio.Media.DURATION));
SimpleDateFormat sdf=new SimpleDateFormat("mm:ss");
String time = sdf.format(new Date(aLong));
LocalMusicBean localMusicBean = new LocalMusicBean(sid, song, singer, time, path);
mDatas.add(localMusicBean);
}
adapter.notifyDataSetChanged();
}
播放/暂停 上下首按钮
@Override
public void onClick(View v) {
switch (v.getId())
{
case R.id.local_music_last:
if (currentPlayStation<=0) {
Toast.makeText(this,"已经到顶了",Toast.LENGTH_SHORT).show();
return;
}
currentPlayStation--;
LocalMusicBean lastBean=mDatas.get(currentPlayStation);
playMusicPosition(lastBean);
break;
case R.id.local_music_next:
if (currentPlayStation==mDatas.size()-1) {
Toast.makeText(this,"已经到底了",Toast.LENGTH_SHORT).show();
return;
}
currentPlayStation++;
LocalMusicBean nextBean=mDatas.get(currentPlayStation);
playMusicPosition(nextBean);
break;
case R.id.local_music_start:
if (currentPlayStation==-1)
{
Toast.makeText(this,"请选择要播放的音乐",Toast.LENGTH_SHORT).show();
return;
}
if (mediaPlayer.isPlaying())
{
pauseMusic();
} else {
playMusic();
}
break;
}
}
还需要注意的地方
-
因为要获取本地文件的权限需要在AndroidManifest.xml中添加代码
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
同时在虚拟机中将该应用的读写权限打开 -
主界面的按钮样式开始可能修改不了,要在res/themes.xml中更改代码
在DayNight.DarkActionBar后加.Bridge
<style name="Theme.MusicPlaayer" parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge">
- 暂停音乐时要记录当前播放的位置,然后继续播放时需要从上一次暂停的位置播放音乐,切换音乐时则将该位置置为0.
- 注意播放第一首时不能播放上一首,最后一首时不能播放下一首,刚开始进入播放时不能点击播放按钮等交互问题.
- 虚拟机中没有本地音乐的话可以先安装一个播放器(网易云,酷狗等)然后再下载一些音乐.
展示
- 进入界面
-
点击列表播放
-
暂停播放
-
下一首
代码仓库地址