关于音乐播放器,我真的是接触比较多,听歌作为我第一大爱好,之前也用Java设计过音乐播放器,感兴趣的同学可以阅读:Android Studio如何实现音乐播放器(简单易上手)和 Android Studio实现音乐播放器2.0
一、实验目的
理论知识
- 掌握Kotlin面向对象的软件开发方面的基础知识。
- 巩固前期Activity、UI控件的使用。
- 掌握Service和BroadcastReceiver的特点及用法。
专业技能
- 熟悉Android软件开发环境并掌握具体的工具的使用。
- 掌握Service和BroadcastReceiver组件的使用。
- 掌握移动应用软件分析和设计方法,并能将其运用到工程实践当中。
职业素养
- 逐步形成系统的设计的思想,具有一定的创新精神。
- 养成良好的编程习惯。
二、实验内容
根据Service及BroadcastReceiver的知识讲解和案例使用,实现一个Android音乐播放器,强化对服务与广播的理解。要求能实现音乐的播放,暂停,上一首,下一首等功能。要求:
- 巩固Android应用开发工具(Eclipse或者Android Studio)的常规用法;
- 巩固Activity、UI控件的常规用法;
- 掌握Service和BroadcastReceiver的编程要点;
- 理解MediaPlayer的使用。
三、实验步骤
1、页面布局
先考虑下简单音乐播放器的元素,那肯定是播放暂停停止,上一首和下一首了。
父布局是RelativeLayout,然后是ListView显示歌单,接下去就是Button按键了,没什么需要讲的,都过于基础。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/lv_music"
android:layout_width="match_parent"
android:layout_height="500dp"/>
<LinearLayout
android:id="@+id/ll_play"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="@+id/lv_music"
android:layout_marginTop="20dp">
<Button
android:id="@+id/btn_start"
android:layout_width="0dp"
android:layout_weight="1"
android:text="开始播放"
android:textSize="20sp"
android:gravity="center"
android:layout_margin="5dp"
android:background="@drawable/btn_selector"
android:layout_height="match_parent"/>
<Button
android:id="@+id/btn_pause"
android:layout_width="0dp"
android:layout_weight="1"
android:text="暂停播放"
android:textSize="20sp"
android:gravity="center"
android:layout_margin="5dp"
android:background="@drawable/btn_selector"
android:layout_height="match_parent"/>
<Button
android:id="@+id/btn_stop"
android:layout_width="0dp"
android:layout_weight="1"
android:text="停止播放"
android:textSize="20sp"
android:gravity="center"
android:layout_margin="5dp"
android:background="@drawable/btn_selector"
android:layout_height="match_parent"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="@+id/ll_play"
android:layout_marginTop="20dp">
<Button
android:id="@+id/btn_pre"
android:layout_width="0dp"
android:layout_weight="1"
android:text="上一首"
android:textSize="20sp"
android:gravity="center"
android:layout_margin="5dp"
android:background="@drawable/btn_selector"
android:layout_height="match_parent"/>
<Button
android:id="@+id/btn_next"
android:layout_width="0dp"
android:layout_weight="1"
android:text="下一首"
android:textSize="20sp"
android:gravity="center"
android:layout_margin="5dp"
android:background="@drawable/btn_selector"
android:layout_height="match_parent"/>
</LinearLayout>
</RelativeLayout>
2、音乐服务
其实播放音乐只需要MediaPlayer和start、resume等方法就行,几行代码解决。但Service越来越需要音乐播放器来体现出来,作为四大组件之一,Service从来不露脸,借助Activity来发挥自己的才能。是四大组件里面和Content Provider一样低调的人。
首先定义mediaPlayer对象。然后重写 onCreate()
方法,在里面给mediaPlayer初始化和initMediaPlayer()
,init的方法中就是打开assets文件夹下的音乐,调用setDataSource()
设置数据源,然后prepare()
准备就绪。
private lateinit var mediaPlayer:MediaPlayer
private var index = 0
override fun onCreate() {
super.onCreate()
mediaPlayer = MediaPlayer()
initMediaPlayer()
}
fun initMediaPlayer() {
val assetManager = assets
var fileName = "music" + index + ".mp3"
var fd = assetManager.openFd(fileName)
mediaPlayer.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)
mediaPlayer.prepare()
}
既然要通过Service实现音乐服务,那么就要控制音乐播放,在MusicService类中定义一个内部类MusicControl。它继承自Binder,里面只有成员方法,而且都没有返回值,其实就是对mediaplaer的方法进行了封装。start()、pause()、reset(),全局变量index是歌曲下标,在切换上下首时调用。
inner class MusicControl:Binder() {
fun playMusic() {
if (!mediaPlayer.isPlaying) {
mediaPlayer.start()
}
}
fun pasueMusic() {
if (mediaPlayer.isPlaying) {
mediaPlayer.pause()
}
}
fun stopMusic() {
if (mediaPlayer.isPlaying) {
mediaPlayer.reset()
initMediaPlayer()
}
}
fun prePlay() {
// 循环播放前一首
index = (index + 5) % 6
// 如果正在播放则重置播放器
if (mediaPlayer.isPlaying) {
mediaPlayer.reset()
}
initMediaPlayer()
mediaPlayer.start()
}
fun nextPlay() {
// 循环播放下一首
index = (index + 7) % 6
// 如果正在播放则重置播放器
if (mediaPlayer.isPlaying) {
mediaPlayer.reset()
}
initMediaPlayer()
mediaPlayer.start()
}
}
3、音乐播放
创建适配器,使用默认的simple_list_item_1,显示一行歌曲名就行。如果你想自定义加上其他的歌曲元素,可以自己创建一个适配器和子项布局文件。这里讲解的重点是Service和Activity进行绑定。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, musicList)
binding.lvMusic.adapter = adapter
// 定义意图对象,绑定服务自动创建
musicIntent = Intent(this, MusicService::class.java)
bindService(musicIntent, musicConnection, BIND_AUTO_CREATE)
initView()
}
首先MainActivity里面还需要定义个内部类MusicConnection,用于连接MusicService的内部类,继承自ServiceConnection,重写的分类方法中只是在连接上服务的时候将iBinder赋值给musicControl。这里musicControl就是MusicService的内部类对应的对象。
lateinit var musicControl:MusicService.MusicControl
inner class MusicConnection:ServiceConnection {
override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
musicControl = p1 as MusicService.MusicControl
}
override fun onServiceDisconnected(p0: ComponentName?) {
}
}
下面我们就用初始化好的MusicConnection对象来连接MainActivity和MusicService。很简单的两句就好了。
musicIntent = Intent(this, MusicService::class.java)
bindService(musicIntent, musicConnection, BIND_AUTO_CREATE)
下面我们设置下按钮的点击事件,其实就是直接调用musicControl对象的方法。
override fun onClick(p0: View?) {
when(p0?.id) {
R.id.btn_start->{
musicControl.playMusic()
}
R.id.btn_pause->{
musicControl.pasueMusic()
}
R.id.btn_stop->{
musicControl.stopMusic()
}
R.id.btn_pre->{
musicControl.prePlay()
}
R.id.btn_next->{
musicControl.nextPlay()
}
}
}
四、运行演示
打开就是主页面,点击开始播放,从第一首开始,然后可以暂停播放,再点开始播放就是继续播放,随时停止播放,上一首和下一首也无比流畅。
五、实验总结
这已经是第四次做音乐播放器了,这次做的也是最快的,也可能是简单的原因,没加什么复杂内容,其实如果是从音乐文件的数据库中读取再播放,我觉得就要花些时间了。或者从SD卡中读文件也是不错的想法,感兴趣的同学可以尝试挑战。
🔥源代码已上传CSDN🔥 |
---|