Android Studio如何实现音乐播放器(简单易上手) 您所在的位置:网站首页 第一个音乐播放器是哪个 Android Studio如何实现音乐播放器(简单易上手)

Android Studio如何实现音乐播放器(简单易上手)

2024-07-12 04:09| 来源: 网络整理| 查看: 265

我们大家平时长时间打代码的时候肯定会感到疲惫和乏味,这个时候一边播放自己喜欢的音乐,一边继续打代码,心情自然也愉快很多。音乐带给人的听觉享受是无可比拟的,动听的音乐可以愉悦人的身心,让人更加积极地去热爱生活。大家平常应该会用QQ音乐、网易云音乐或者酷狗音乐等音乐APP来听歌,想不想拥有属于自己的音乐播放器。那么接下来就教大家如何用Android Studio自己制作一个音乐播放器App。

项目目录 一、项目概述1、需求分析2、设计分析3、资源文件分析 二、开发环境三、准备工具四、详细设计1、新建工程2、搭建主界面3、创建服务类3.1、服务概述3.2、服务的创建3.3、服务的启动方式3.4、服务的生命周期 4、搭建音乐播放界面5、搭建音乐列表界面6、搭建专辑界面7、导入资源文件 五、项目运行1、创建模拟器2、运行演示 六、项目总结七、源码下载八、升级优化

一、项目概述 1、需求分析

综合运用UI界面设计、数据存储、Activity(活动)、Service(服务)、MusicPlayer、ListView等知识,设计开发一款具有音乐列表的音乐播放器。

在这里插入图片描述

2、设计分析

整个项目包含五个类和五个布局文件:

其中frag1、frag2为java文件,MusicActivity为Activity文件,MusicService为Service文件,MainActivity为项目创建时自动生成的Activity文件。

在这里插入图片描述

activity_main为MainActivity的布局文件,显示运行APP时的主界面。activity_music为MusicActivity的布局文件,显示音乐播放器界面。music_list和item_layout一起组成frag1的布局文件,就是音乐列表界面。frag2_layout就是frag2的布局文件,主要显示的是专辑封面图片。 在这里插入图片描述 3、资源文件分析

在res文件夹下创建了raw文件夹,放了三首音乐文件(从音乐软件中下载即可),在drawable文件夹中粘贴了音乐封面图片bg.jpg和播放器背景图片music_bg.jpg,还有背景选择器的btn_bg_selector.xml文件,如图所示:

在这里插入图片描述

二、开发环境

我的开发环境如下,大家的AS版本不需要和我相同,只要是近两年从官网下载的版本,都是比3.6.1高的,是可以满足运行和开发要求的。

在这里插入图片描述

三、准备工具

选择几首自己下载好的音乐文件,命名为music0、music1、music2等,这里歌曲都要是mp3类型的,数量随意。歌曲名的下标是从0开始的,因为代码中我设置的url地址是从0开始的,否则会闪退。

选择每首歌对应的歌手图片,剪成圆形并且保存好,命名为music0、music1、music2等。图片一定要剪成圆形,椭圆会影响运行效果,导致闪退,如果不太清楚图片如何剪成圆形,可以看这篇博客:如何将图片剪成圆形,也非常简单。

准备一张音乐播放器的背景图片,命名为music_bg,再找一张图片用作专辑图片,命名为bg。图片的后缀是.png或.jpg。

四、详细设计 1、新建工程

首先打开Android Studio,并新建一个工程,File——>New——>New Project——>Empty Project,工程名称叫做Music_List,可以根据自己喜好设置名称。

包名自己随意设定,这里博主用的是zj.dzh,一般是com.android;工程文件的保存路径要修改一下,不要放在C盘,我这里选择的是放在E盘的一个Projects文件夹中,养成项目统一放在英文路径下的好习惯。

最后选择API 18:Android 4.3,因为这样它就拥有了99.5%的跨平台性(兼容性非常好),因为它版本很低,基本上模拟器API版本都是高于20的,所以这个软件可以运行其他各种设备上。点击Finish完成创建。

在这里插入图片描述

2、搭建主界面

设计一个app的时候,一定要先设计layout文件,再设计java文件,因为布局有了,才能在上面进行代码的编写。我们来看一下activity_main布局文件,它主要显示主界面。什么是主界面,就是一个APP运行后默认显示的界面。

最外层用的是LinearLayout线性布局,然后设置的是垂直排列。里面放了两个小的LinearLayout,分别是最上面的一个TextView,内容设置的是“我喜欢”,接着第二个小的LinearLayout放两个水平的TextView控件,内容显示的是“歌曲”和“专辑”。

最下面的剩余空间全部给了Fragment,它的id是content,这里不知道Fragment没关系,反正就晓得它和TextView一样可以显示内容就行。效果如图:

Fragment是一种可以嵌入在活动中的UI片段,能够让程序更加合理和充分地利用大屏幕的空间,出现的初衷是为了适应大屏幕的平板电脑,可以将其看成一个小型Activity,又称作Activity片段。

在这里插入图片描述

完整代码如下:

然后回到我们的Activity文件。MainActivity类是整个工程的主类,首先创建需要用到的控件,然后绑定控件,再设置监听器,底部导航栏设置的是两个菜单文件:frag1(歌曲菜单)和frag2(专辑菜单),默认情况下展示frag1歌曲菜单,点击切换显示frag2专辑菜单。代码如下:

package zj.dzh.music_list; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity implements View.OnClickListener { //创建需要用到的控件的变量 private TextView tv1,tv2; private FragmentManager fm; private FragmentTransaction ft; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定控件 tv1=(TextView)findViewById(R.id.menu1); tv2=(TextView)findViewById(R.id.menu2); //设置监听器,固定写法 tv1.setOnClickListener(this); tv2.setOnClickListener(this); //若是继承FragmentActivity,fm=getFragmentManger(); fm=getSupportFragmentManager(); //fm可以理解为Fragment显示的管理者,ft就是它的改变者 ft=fm.beginTransaction(); //默认情况下就显示frag1 ft.replace(R.id.content,new frag1()); //提交改变的内容 ft.commit(); } @Override //控件的点击事件 public void onClick(View v){ ft=fm.beginTransaction(); //切换选项卡 switch (v.getId()){ case R.id.menu1: ft.replace(R.id.content,new frag1()); break; case R.id.menu2: ft.replace(R.id.content,new frag2()); break; default: break; } ft.commit(); } } 3、创建服务类 3.1、服务概述

在这里插入图片描述

3.2、服务的创建

在这里插入图片描述 创建MusicService文件,右击包名——>New——>Service——>Service,如图:

在这里插入图片描述

命名为MusicService,然后点击Finish。

在这里插入图片描述

3.3、服务的启动方式

在这里插入图片描述

3.4、服务的生命周期

在这里插入图片描述 MusicService代码:

package zj.dzh.music_list; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Message; import java.util.Timer; import java.util.TimerTask; //这是一个Service服务类 public class MusicService extends Service { //声明一个MediaPlayer引用 private MediaPlayer player; //声明一个计时器引用 private Timer timer; //构造函数 public MusicService() {} @Override public IBinder onBind(Intent intent){ return new MusicControl(); } @Override public void onCreate(){ super.onCreate(); //创建音乐播放器对象 player=new MediaPlayer(); } //添加计时器用于设置音乐播放器中的播放进度条 public void addTimer(){ //如果timer不存在,也就是没有引用实例 if(timer==null){ //创建计时器对象 timer=new Timer(); TimerTask task=new TimerTask() { @Override public void run() { if (player==null) return; int duration=player.getDuration();//获取歌曲总时长 int currentPosition=player.getCurrentPosition();//获取播放进度 Message msg= MusicActivity.handler.obtainMessage();//创建消息对象 //将音乐的总时长和播放进度封装至bundle中 Bundle bundle=new Bundle(); bundle.putInt("duration",duration); bundle.putInt("currentPosition",currentPosition); //再将bundle封装到msg消息对象中 msg.setData(bundle); //最后将消息发送到主线程的消息队列 MusicActivity.handler.sendMessage(msg); } }; //开始计时任务后的5毫秒,第一次执行task任务,以后每500毫秒(0.5s)执行一次 timer.schedule(task,5,500); } } //Binder是一种跨进程的通信方式 class MusicControl extends Binder{ public void play(int i){//String path Uri uri=Uri.parse("android.resource://"+getPackageName()+"/raw/"+"music"+i); try{ //重置音乐播放器 player.reset(); //加载多媒体文件 player=MediaPlayer.create(getApplicationContext(),uri); player.start();//播放音乐 addTimer();//添加计时器 }catch(Exception e){ e.printStackTrace(); } } //下面的暂停继续和退出方法全部调用的是MediaPlayer自带的方法 public void pausePlay(){ player.pause();//暂停播放音乐 } public void continuePlay(){ player.start();//继续播放音乐 } public void seekTo(int progress){ player.seekTo(progress);//设置音乐的播放位置 } } //销毁多媒体播放器 @Override public void onDestroy(){ super.onDestroy(); if(player==null) return; if(player.isPlaying()) player.stop();//停止播放音乐 player.release();//释放占用的资源 player=null;//将player置为空 } } 4、搭建音乐播放界面

在这里插入图片描述

右击包名,新建一个Activity,命名为MusicActivity,点击Finish,它会自动生成一个activity_music的布局文件,用来显示音乐播放界面,如图所示:

在这里插入图片描述

(1)MusicActivity类:通过onClick方法控制着音乐的播放、暂停、继续播放和退出功能。它和MusicService进行绑定连接。在音乐播放时显示歌曲总时长,还有歌曲当前播放时长,控制歌曲进度条的移动。代码如下:

package zj.dzh.music_list; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; import android.animation.ObjectAnimator; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.view.View; import android.view.animation.LinearInterpolator; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.TextView; import static java.lang.Integer.parseInt; public class MusicActivity extends AppCompatActivity implements View.OnClickListener{ //进度条 private static SeekBar sb; private static TextView tv_progress,tv_total,name_song; //动画 private ObjectAnimator animator; private MusicService.MusicControl musicControl; private String name; private Intent intent1,intent2; private MyServiceConn conn; //记录服务是否被解绑,默认没有 private boolean isUnbind =false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_music); //获取从frag1传来的信息 intent1=getIntent(); init(); } private void init(){ //进度条上小绿点的位置,也就是当前已播放时间 tv_progress=(TextView)findViewById(R.id.tv_progress); //进度条的总长度,就是总时间 tv_total=(TextView)findViewById(R.id.tv_total); //进度条的控件 sb=(SeekBar)findViewById(R.id.sb); //歌曲名显示的控件 name_song=(TextView)findViewById(R.id.song_name); //绑定控件的同时设置点击事件监听器 findViewById(R.id.btn_play).setOnClickListener(this); findViewById(R.id.btn_pause).setOnClickListener(this); findViewById(R.id.btn_continue_play).setOnClickListener(this); findViewById(R.id.btn_exit).setOnClickListener(this); name=intent1.getStringExtra("name"); name_song.setText(name); //创建一个意图对象,是从当前的Activity跳转到Service intent2=new Intent(this,MusicService.class); conn=new MyServiceConn();//创建服务连接对象 bindService(intent2,conn,BIND_AUTO_CREATE);//绑定服务 //为滑动条添加事件监听,每个控件不同果然点击事件方法名都不同 sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { //这一行注解是保证API在KITKAT以上的模拟器才能顺利运行,也就是19以上 @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { //进当滑动条到末端时,结束动画 if (progress==seekBar.getMax()){ animator.pause();//停止播放动画 } } @Override //滑动条开始滑动时调用 public void onStartTrackingTouch(SeekBar seekBar) { } @Override //滑动条停止滑动时调用 public void onStopTrackingTouch(SeekBar seekBar) { //根据拖动的进度改变音乐播放进度 int progress=seekBar.getProgress();//获取seekBar的进度 musicControl.seekTo(progress);//改变播放进度 } }); //声明并绑定音乐播放器的iv_music控件 ImageView iv_music=(ImageView)findViewById(R.id.iv_music); String position= intent1.getStringExtra("position"); //praseInt()就是将字符串变成整数类型 int i=parseInt(position); iv_music.setImageResource(frag1.icons[i]); //rotation和0f,360.0f就设置了动画是从0°旋转到360° animator=ObjectAnimator.ofFloat(iv_music,"rotation",0f,360.0f); animator.setDuration(10000);//动画旋转一周的时间为10秒 animator.setInterpolator(new LinearInterpolator());//匀速 animator.setRepeatCount(-1);//-1表示设置动画无限循环 } //handler机制,可以理解为线程间的通信,我获取到一个信息,然后把这个信息告诉你,就这么简单 public static Handler handler=new Handler(){//创建消息处理器对象 //在主线程中处理从子线程发送过来的消息 @Override public void handleMessage(Message msg){ Bundle bundle=msg.getData();//获取从子线程发送过来的音乐播放进度 //获取当前进度currentPosition和总时长duration int duration=bundle.getInt("duration"); int currentPosition=bundle.getInt("currentPosition"); //对进度条进行设置 sb.setMax(duration); sb.setProgress(currentPosition); //歌曲是多少分钟多少秒钟 int minute=duration/1000/60; int second=duration/1000%60; String strMinute=null; String strSecond=null; if(minute strMinute=minute+""; } if (second strSecond=second+""; } //这里就显示了歌曲总时长 tv_total.setText(strMinute+":"+strSecond); //歌曲当前播放时长 minute=currentPosition/1000/60; second=currentPosition/1000%60; if(minute strMinute=minute+" "; } if (second strSecond=second+" "; } //显示当前歌曲已经播放的时间 tv_progress.setText(strMinute+":"+strSecond); } }; //用于实现连接服务,比较模板化,不需要详细知道内容 class MyServiceConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service){ musicControl=(MusicService.MusicControl) service; } @Override public void onServiceDisconnected(ComponentName name){ } } //判断服务是否被解绑 private void unbind(boolean isUnbind){ //如果解绑了 if(!isUnbind){ musicControl.pausePlay();//音乐暂停播放 unbindService(conn);//解绑服务 } } @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_play://播放按钮点击事件 String position=intent1.getStringExtra("position"); int i=parseInt(position); musicControl.play(i); animator.start(); break; case R.id.btn_pause://暂停按钮点击事件 musicControl.pausePlay(); animator.pause(); break; case R.id.btn_continue_play://继续播放按钮点击事件 musicControl.continuePlay(); animator.start(); break; case R.id.btn_exit://退出按钮点击事件 unbind(isUnbind); isUnbind=true; finish(); break; } } @Override protected void onDestroy(){ super.onDestroy(); unbind(isUnbind);//解绑服务 } }

(2)activity_music: 显示音乐播放器界面,包括图片转动,歌曲名传值,还有播放、暂停播放、继续播放和退出四个控制按钮。效果如图:

在这里插入图片描述 activity_music代码如下:

(3)右击drawable文件夹,New——>Drawable Resource File,命名为btn_bg_selector,如图:

在这里插入图片描述

该文件为按钮的背景选择器,是当播放等按钮按下的时候变成灰色,未按下显示白色,当然可以自由设定颜色。代码如下:

5、搭建音乐列表界面

右击包名——>New——>Java Class,命名为frag1,点击OK。如图:

在这里插入图片描述

(1)frag1类:显示歌曲列表,手机模拟器运行出来的默认界面,就是将歌曲名、歌曲图片以列表的形式显示出来,注释很详细,代码如下:

package zj.dzh.music_list; import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import androidx.fragment.app.Fragment; public class frag1 extends Fragment { private View view; //创建歌曲的String数组和歌手图片的int数组 public String[] name={"邓紫棋——光年之外","蔡健雅——红色高跟鞋","Taylor Swift——Love Story"}; public static int[] icons={R.drawable.music0,R.drawable.music1,R.drawable.music2}; @Override public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ //绑定布局,只不过这里是用inflate()方法 view=inflater.inflate(R.layout.music_list,null); //创建listView列表并且绑定控件 ListView listView=view.findViewById(R.id.lv); //实例化一个适配器 MyBaseAdapter adapter=new MyBaseAdapter(); //列表设置适配器 listView.setAdapter(adapter); //列表元素的点击监听器 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { //创建Intent对象,参数就是从frag1跳转到MusicActivity Intent intent=new Intent(frag1.this.getContext(), MusicActivity.class); //将歌曲名和歌曲的下标存入Intent对象 intent.putExtra("name",name[position]); intent.putExtra("position",String.valueOf(position)); //开始跳转 startActivity(intent); } }); return view; } //这里是创建一个自定义适配器,可以作为模板 class MyBaseAdapter extends BaseAdapter{ @Override public int getCount(){return name.length;} @Override public Object getItem(int i){return name[i];} @Override public long getItemId(int i){return i;} @Override public View getView(int i ,View convertView, ViewGroup parent) { //绑定好VIew,然后绑定控件 View view=View.inflate(frag1.this.getContext(),R.layout.item_layout,null); TextView tv_name=view.findViewById(R.id.item_name); ImageView iv=view.findViewById(R.id.iv); //设置控件显示的内容,就是获取的歌曲名和歌手图片 tv_name.setText(name[i]); iv.setImageResource(icons[i]); return view; } } }

(2)右击layout文件夹——>New———>Layout Resource File,新建两个layout文件,分别命名为music_list(listview列表布局)和item_layout(子项布局),这两个布局文件对应着frag1逻辑代码,显示歌曲列表。如图所示:

在这里插入图片描述

music_list:歌曲列表布局文件,和QQ好友列表相似,垂直显示多条记录。效果如图:

在这里插入图片描述

music_list代码如下:

item_layout: 就是条目布局,和上面的music_list列表一起组合使用,它就是相当于列表中每一行子项的具体布局,布局效果如图:

,

item_layout代码如下:

6、搭建专辑界面

右击包名,New——>Java Class,命名为frag2,点击OK。如图:

在这里插入图片描述

(1)frag2类:展示的封面专辑图片,在主界面点击专辑按钮跳转到此界面。代码如下:

package zj.dzh.music_list; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.fragment.app.Fragment; public class frag2 extends Fragment { //创建一个View private View zj; //显示布局 public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { zj = inflater.inflate(R.layout.frag2_layout, null); return zj; } }

(2)再新建一个layout文件,命名为frag2_layout,如图:

在这里插入图片描述

frag2_layout用来设置一个ImageView,显示专辑图片。当然frag2可以自由发挥,比如说设置成歌手资料、MV列表或者排行榜等等,比如音乐播放器2.0是歌手列表,多媒体播放器是MV列表。代码如下:

7、导入资源文件

在res文件夹下新建一个raw文件夹,将刚刚准备好的音乐文件复制粘贴到raw文件夹中。对应的封面圆形图片、背景图片和专辑图片都复制粘贴到drawable中,这里博主只选择了三首歌曲和三张封面圆形图片,歌曲数量由大家自己设置,没有限制。

再次提醒下,注意命名哦;歌曲文件后缀是.mp3,在Android中打开是乱码不用担心,我们不需要打开它。

在这里插入图片描述

至此,完整的音乐播放器项目创建完成。

五、项目运行 1、创建模拟器

选择自己的模拟器运行,如果没有模拟器可以点击AVD,选择新建模拟器,选择手机型号Pixel 2:

在这里插入图片描述 选择高于21的API版本进行下载,下载成功之后next完成创建,如图:

在这里插入图片描述

2、运行演示

(1)运行app到模拟器上,显示主界面:

在这里插入图片描述 (2)点击专辑选项卡:

在这里插入图片描述

(3)再选择歌曲选项卡,选择第一首歌《光年之外》并打开,跳转到音乐播放页面,歌曲的封面图片显示在正中间,发现《光年之外》的歌名也传递过来了:

在这里插入图片描述

(4)点击播放音乐按钮,音乐开始播放,进度条开始滑动,图片开始转动:

在这里插入图片描述

(5)点击暂停播放按钮,音乐停止播放,而且进度条停止滑动,图片也停止转动:

在这里插入图片描述

(6)点击继续播放按钮,音乐继续播放,歌手图片也继续旋转:

在这里插入图片描述

(7)点击退出按钮,会退回到主界面:

在这里插入图片描述

(8)选择第二首歌《红色高跟鞋》并播放,这里进度条可以自由拖动,歌曲也会随之播放到对应位置:

在这里插入图片描述

(9)选择第三首歌《Love Story》并播放:

在这里插入图片描述

运行效果和功能很完整,至此就完成了非常简单的音乐播放器。大家可以跟着动手做一下,放上自己喜欢的爱豆图片,还有喜欢的歌,体验感真的不要太好!

六、项目总结

这次音乐播放器工程,可以让大家熟练掌握Android程序开发的基本技术,涉及Android 基础知识、UI界面、数据存储、四大组件、网络编程、高级编程等。大家熟练掌握可以对以后的Android开发有很大的帮助。

七、源码下载 1️⃣ 点击右侧链接直接下载源代码Android Studio实现音乐播放器2️⃣文末公众号 后台回复:音乐播放器

博主从头到尾详细讲述了该项目的搭建运行步骤,代码里面也有详细的注释,如果对你有帮助的话,记得三连支持下哦。下方还有最新的音乐播放器2.0版本。

八、升级优化 今天是2021.7.10,博主对这个app进行了次更新,优化了播放器界面和上一首下一首功能,大家点击链接就可以直接跳转进行学习👉🏻:Android Studio实现音乐播放器2.0,喜欢的小伙伴多多三连支持哦! 🚀这有你错过的精彩内容Android Studio实现文艺阅读App Android Studio实现志愿者系统Android Studio实现多功能日记本Android Studio实现推箱子小游戏Android Studio实现五子棋小游戏


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有