vlambda博客
学习文章列表

17 Android Studio开发实战:音乐播放器——浪花音乐

手机上的多媒体内容讲究声情并茂、悦目且悦耳,这样才能让用户的感官得到最大享受。影视播放器由于存在视频自身的画面,反而限制了开发者的施展空间;而音乐播放器允许定制播放画面,开发者有足够空间施展拳脚。本节以“音乐播放器—— 浪花音乐”为实战项目,通过该项目的编码练习巩固和提高开发者的实战技能。

1  设计思路

大家常见的主流音乐播放器(如QQ音乐、酷狗音乐、酷我音乐、网易云音乐、虾米音乐、百度音乐等)不外乎有3项播放功能:

1)展示音乐和歌曲列表。

2)在歌曲详情页面滚动展示歌词,并高亮显示当前正在播放的歌词片段。

3)通过音乐控制条显示播放进度,并提供开始与暂停、拖动播放的功能。

只看文字描述有点抽象,还是先给出播放器的效果图,方便查找对应的功能。如图所示为播放器的歌曲列表页面。

17 Android Studio开发实战:音乐播放器——浪花音乐

点击顶部的“打开音乐文件”会弹出文件对话框,用于选择音频文件;底部是播放器的控制条,中间为当前手机上的所有音乐文件列表。点击某个音乐项,进入该音乐的详情页面,如图所示。

17 Android Studio开发实战:音乐播放器——浪花音乐

页面顶部显示歌曲名称和演唱者,页面底部是播放器控制条,页面中间为该歌曲对应的歌词内容。

接下来对音乐播放器的3项功能进行详细剖析。

对于第一点的展示歌曲列表,让用户手动添加不但费时费力,而且用户往往搞不清楚手机上的歌曲都放在哪个目录。我们假设用户是“傻白甜”,开发者做的App就得智能贴心,主动帮用户把手机上的歌曲找出来。要想实现这个功能,可以通过内容组件访问系统自带的媒体库,查找并显示媒体库中的歌曲列表。

对于第二点的滚动歌词显示,常见的歌词文件是LRC格式的文本文件,内容主要是每句歌词的文字与开始时间。文本文件的解析并不复杂,难点主要是滚动显示。乍看歌词从下往上滚动,适合采用平移动画,然而歌词滚动不是匀速的,因为每句歌词的间隔时间并不固定,只能把整个歌词滚动分解为若干动画,有多少行就有多少个动画。

对于第三点的音乐控制条,总体上使用前面提到的视频控制条。不过音乐控制条更加复杂,因为除了控制音频的播放,还要控制歌词动画的播放。另外,音乐控制条显示在歌曲列表页面上,为了与主流播放器看齐,最好在系统通知栏固定放置音乐控制条。

弄懂了音乐播放器的主要功能,再来看该播放器用到的App开发技术。

1服务Service歌曲播放不依赖于某个页面,即使用户回到桌面,歌曲也要继续播放,因此必须在后台服务中播放歌曲。

2应用Application正在播放的歌曲名称,在播放器的任何页面都能看到,用到了全局内存,要把歌曲名称保存在自定义的Application类中。

3内容解析器ContentResolver系统媒体库中的音频文件,需要通过内容解析器访问媒体库的音频资源,详细路径是MediaStore.Audio.Media.EXTERNAL_CONTENT_URI

4文件存取:歌词文件与音乐文件在同一个目录下,文件名一样,只是扩展名变为lrc

5通知Notification系统通知栏要显示音乐控制条,就得把后台服务以通知的形式在前台运行。

6媒体播放器MediaPlayer播放音频文件,自然会用到媒体播放器。

7音频控制条AudioController跟影视播放器一样,自定义样式的控制条更能满足个性化的定制要求。

8按键事件KeyEvent与音量对话框VolumeDialog用户按手机侧面的加、减键,播放器应弹出音量调节对话框,供用户调整音量大小。

9动画Animation歌词的滚动显示,可使用平移动画,也可使用属性动画实现歌词滚动效果。

10其余高级控件:如列表视图ListView、进度条ProgressBar、拖动条SeekBar等,有待读者进一步发掘。

不看不知道,一看吓一跳。如果仅播放声音,技术上只要ActivityMediaPlayer就行,最多再加一个媒体控制条MediaController,三板斧够用了。但是要让播放器变得生动活泼,要让用户真正去欣赏音乐,开发者要做的工作就不是实现基础功能,而是从界面设计到用户体验,每个细节都要充分考虑,所以实际运用的技术远远不止三板斧。

2  小知识:可变字符串SpannableString

大家都知道,文本控件家族显示文本内容使用setText方法,使用setTextColor方法设置文本颜色,使用setTextSize方法设置文本大小,使用setTextAppearance方法设置文本样式(包括颜色、大小、风格等)。普通的用法只能对控件的所有文本做统一设置,如果想对前一段文本加大加粗,对中间一段文本显示红色,再将后面一段文本换成图像,就无能为力了。为了解决分段文本使用不同样式的需求,Android提供了可变字符串SpannableString,通过该工具实现对文本分段显示。

SpannableString的原理是给指定位置的文本赋予对应的样式,从而告知系统这段文本的显示方式。具体到编码有3个步骤,说明如下:

  • 步骤1

从指定文本字符串构造一个SpannableString对象

  • 步骤2

调用SpannableString对象的setSpan方法设置指定文本段的显示风格该方法的第一个参数为风格样式对象第二个参数为文本段的起始位置3个参数为文本段的终止位置4个参数为风格的范围标志用来标识在文本段前后输入新字符时是否令它们应用这个风格(主要对EditText起作用)风格范围标志的取值说明见下表

17 Android Studio开发实战:音乐播放器——浪花音乐

  • 步骤3

用文本控件对象的setText方法设置定义好的SpannableString对象

显示风格的定义在android.text.style包中,总共有30多个。当然,常用的没这么多,笔者整理了8个常用的显示风格,详见下表

17 Android Studio开发实战:音乐播放器——浪花音乐

17 Android Studio开发实战:音乐播放器——浪花音乐

下面是使用SpannableString设置文字样式的代码:

17 Android Studio开发实战:音乐播放器——浪花音乐
17 Android Studio开发实战:音乐播放器——浪花音乐
17 Android Studio开发实战:音乐播放器——浪花音乐

SpannableString的不同风格效果如图1~图6所示。其中,如图1所示为加大字体后的效果,如图2所示为加粗字体后的效果,如图3所示为修改文字颜色后的效果,如图4所示为修改文字背景后的效果,如图5所示为增加下划线后的效果,如图6所示为把文字替换成图片后的效果。

17 Android Studio开发实战:音乐播放器——浪花音乐

17 Android Studio开发实战:音乐播放器——浪花音乐

17 Android Studio开发实战:音乐播放器——浪花音乐

读者是否对图6似曾相识?使用QQ聊天时会自动把特定字符转成表情图片,比如把文字内容中的“:)”显示为笑脸图片,在Android设备上可通过SpannableString实现该功能。

3  代码示例

编码与测试方面需要注意以下5点:

1)如果把动画描述定义在XML文件中,动画定义文件就要放在res/anim目录下。

2)打开音乐文件,要记得为AndroidManifest.xml添加SD卡的权限配置:

17 Android Studio开发实战:音乐播放器——浪花音乐

3AndroidManifest.xmlapplication节点注意补充android:name=".MainApplication";另外,注册音乐播放服务的service,注册代码如下:

17 Android Studio开发实战:音乐播放器——浪花音乐

4)测试设备的Android版本要求不低于Android 4.4,因为属性动画的暂停和恢复方法是在4.4后引入的。

5)要在真机上测试实战项目,如果在模拟器上测试,就会发现MP3标题乱码。这是因为中文歌曲的MP3标签采用GBK编码,而模拟器采用UTF8编码,两者对汉字的编码格式不一致。如果用真机测试,国产机厂商已经帮我们解决了汉字编码问题。

具体的代码编写还存在3个技术要点,记录如下:

1. 使用内容解析器ContentResolver访问媒体库

音频资源对应的内容路径是MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,内容解析器通过query方法访问该URI获得记录游标,还得把详细记录字段逐个读取出来,音频资源的字段信息说明见下表。

17 Android Studio开发实战:音乐播放器——浪花音乐

2. 解析LRC歌词文件

简要介绍一下LRC文件的内容格式,开发者关心的主要是内部的时间信息与歌词文字。下面是一个LRC歌词的片段:

17 Android Studio开发实战:音乐播放器——浪花音乐

歌词第一行有一个offset标签,表示歌词标注的时间与音乐文件的时间偏移。歌词行的前面是中括号括起来的时间戳,时间戳的数据格式为“分:.毫秒”,表示该行歌词的起始时间。如果某行歌词被演唱多遍,那么歌词文字前面会有多个时间戳。

3. 歌词滚动动画的播放控制

一般动画启动后很快就会结束,但歌词滚动动画不是这样的,用户点击控制条上的暂停按钮,不但播放器要暂停播放,而且歌词要暂停滚动。平移动画TranslateAnimation不支持暂停和恢复操作,不止平移动画,所有补间动画都不支持暂停和恢复。难道要自己重定义动画?山穷水尽疑无路,柳暗花明又一村。幸好Android提供了属性动画,不但支持所有补间动画效果,而且支持暂停和恢复操作,还等什么,赶紧把TranslateAnimation换成ObjectAnimator吧!

现在音乐播放器的编码没什么难点,如果不出状况,读者就能很快看到自己的App作品。下图所示为音乐播放器的效果画面。

17 Android Studio开发实战:音乐播放器——浪花音乐

点击歌曲列表中的歌名《一剪梅》,进入该歌曲的播放界面,歌词文字随着时间流逝缓慢向上滚动,当前演唱的歌词行会高亮显示。播放一段时间后,控制条的进度移到右边,歌词也大半上翻,高亮的歌词行移向后面的文字,如图所示。

17 Android Studio开发实战:音乐播放器——浪花音乐

接着按返回键,后退到歌曲列表页面,页面下方的控制条显示当前的播放进度,时间计数随着歌曲播放而不断刷新,如图所示。

17 Android Studio开发实战:音乐播放器——浪花音乐

在歌曲列表页面点击歌名《上海滩》,进入该歌曲的播放界面,此时《一剪梅》停止播放,转为播放《上海滩》,如图所示。

17 Android Studio开发实战:音乐播放器——浪花音乐

最后下拉系统通知栏,应该能够看到播放器的控制条,如图所示。在通知栏上不但可以自动刷新播放进度,而且可以进行暂停和恢复播放的操作。

17 Android Studio开发实战:音乐播放器——浪花音乐

下面是音乐播放详情界面与歌词有关的处理代码片段,更多源码参见源码media模块的MusicPlayerActivity.javaMusicDetailActivity.javaMusicService.java

17 Android Studio开发实战:音乐播放器——浪花音乐
17 Android Studio开发实战:音乐播放器——浪花音乐
17 Android Studio开发实战:音乐播放器——浪花音乐
17 Android Studio开发实战:音乐播放器——浪花音乐