介绍

大二下学期的时候做的一个项目,一个在线音乐播放器
UI素材和布局都参考了网易云音乐,客户端使用的是Android编写的,而服务器方面则是自己使用Java Socket,并自定义服务器与客户端之间的通讯协议~(安全方面就比较残念) 完成的功能也比较少~ 本人也只是个小菜鸡(:з)∠)


功能实现 & 实现方法

功能一:登陆,注册

1. 要实现注册和登陆功能,就需要一个服务器,以及一个数据库,用来记录数据

2. 客户端发送注册的信息到服务器,服务器在数据库中检索是否存在此账户,若没有,则将此信息写入数据库中。若账户存在,则返回错误信息给用户,提示用户,注册用户名已存在。并且对用户的输入做一些简单的判断,例如2次密码的输入必须一致。

3. 登陆则是发送账户,密码给服务器,服务器检索数据库,查找是否存在用户,及密码是否正确。

4. 参照网易云音乐的登陆机制,在用户登陆一次后,第二次打开应用时不需要再次登陆,直接进入主界面,关于如何判断是否以及登陆,当登陆之后,一个静态变量isLogin会被记录到本地的sharePreference文件中,每次打开应用的时候,会去查询这个文件中的这个标志变量是否为true,若为true则直接加载主界面activity,finish()登陆注册的activity。当用户登出时(当然这里还没有实现),会把isLogin设置为false,这样下次登陆的时候就要重新进行登陆**

5. 要用到的工具有jdbc-jar和mySql。

6. 服务器方面,自定义协议Login和Register

效果截图如下:
1. 运行app进入登陆注册界面。

2.进入注册界面,输入用户名和密码

3.注册成功,再看看服务器那边的信息,和数据库

4.接下来登陆,输入刚才注册的账号,并登陆,进入到主界面


功能二:在线搜索音乐

1. 自定义通信协议Search,从客户端发送search “seachContent”到服务器,然后服务器在本地的歌曲数据库中去查找,是否存在该歌曲searchContent,若存在则返回查找结果,若不存在,则提示用户尝试别的搜索条件。

效果截图如下:
1. 点击主界面右上角的搜索按钮,进入搜索栏,在搜索栏输入要查找的歌曲,或者歌手,或者专辑。
示例 输入专辑3L,点击搜索,得到结果

2. 再看看服务器方面的信息

服务器接受到了请求,在数据库中去寻找歌曲。(歌曲数据库,在每次启动数据库的时候进行导入)


功能三:在线播放音乐,内置音乐播放器

1. 在线播放音乐,就需要实现缓存,别播边放的功能。

2.服务器接收到了download请求后,在服务器本地找到文件,然后把文件发送到客户端,客户端接收文件,当接收文件大小满足播放要求的大小时,就启动mediaplayer,开始播放接收到的文件,下载和播放是多线程的,由于播放和下载都对文件有读写操作,容易造成死锁。这里把正在下载的文件备份一份给播放器用,本身那份继续进行下载。在快播放完之前导入的文件时,再重新从正在下载的文件中读取内容,继续播放。同时在播放的过程中,已经对播放文件进行了缓存。若要下载此歌曲,可以直接把缓存文件转成MP3文件。在缓存完毕后,本地数据库sqlite会记录缓存文件的路径以及文件的一些信息,待下载的时候做进一步的操作

3.播放器属于一个隐藏的布局,且播放的代码属于多线程,这里本身是想做成service的,但是由于种种原因,还是使用了多线程的办法。在点击选项后,返回主界面,并使隐藏的播放器显示出来。多线程的播放代码对progressbar和button进行了监听和UI刷新。

效果截图:
1.点击搜索的结果返回主界面进行播放,及播放完成状态

功能四:实现下载功能

1. 首先下载是一个比较费时的东西,所以这里采用IntentService,一个服务,一个下载完成后就自动结束的服务,让它来出来下载的操作

2. 下载分为2种,一种是直接从缓存中copy到默认下载目录,另一种是从服务器上下载。

A)  在下载的时候,先检测文件是否存在于本地,若存在则不做任何操作,并Toast提示用户,文件以及存在。B)  若文件不存在,则先从本地数据库中的表cacheFIle中查找是否存在该文件的缓存文件,如果存在,则把该文件copy到默认下载目录中,从表中删除该歌曲的信息C)  若没有缓存,则直接向服务器请求文件,向服务器发送Download请求,服务器返回文件,客户端对文件进行读写,保存在默认目录下D)  BC操作之后,把下载好的歌曲保存在本地数据库中的表dldFile中,以便之后播放本地音乐的时候使用。

效果截图:
1. 再次进入搜索界面输入3l得到查询结果,点击更多详细信息按钮(选项最右边),会得到一个popupWindow弹窗(里面只实现了下载功能,其余的没有实现);点击下载

可以看到,提示信息已经添加到下载队列,因为刚才已经进行了缓存,所以这次下载是直接从缓存目录中去读取文件,转到默认下载目录中。
再检索一首没有缓存的歌曲 示例ao,点击下载

在logcat中显示文件来自服务器。

2.查看默认下载目录文件夹,和数据库文件LocalDatabase


功能五:播放本地音乐功能

1. 在检索函数中预先配置了默认下载目录,所以只会检测该目录下的文件。目前也只能实现检索该目录的功能,因为,音乐文件的解析工作(获取一个音乐文件的专辑,艺术家,歌曲名字)是在服务器进行的,当然这也可以在android上进行,但是一开始没有注意到这点,当注意到的时候程序以及写的七七八八了,再改就可能会耗费很多时间,所以就没改。如果实现android上执行解析,这可能可以省事很多。

2. 检索默认目录中的音乐文件,并从本地数据库中去得到歌曲的信息(专辑,艺术家)。并把这些信息传给List,再通过ListView展示得到的信息。

3. 点击歌曲,调用音乐播放器类里面的playLocalMusic方法,传入该文件的路径,进行播放

效果截图:

点击主界面目录里面的本地音乐,进入本地音乐节目,可以看到显示了刚才下载的2首歌曲。
跟着点击歌曲,返回主界面,可以看到主界面的播放器已经在播放选中的歌曲。


服务器

  1. 首先介绍自定义的协议:Test, Login, Register, Download, Search, 后四种已经介绍过,第一个是用来测试网络是否通畅的,若无法连同网络,则提示用户当前网络不可用。

  2. 服务器自定义了一些错误代码:000,001,002,003; 100,101,102.等等。也可以不用理会,客户端和服务器端彼此都知道的东西。

  3. 服务器连同了MySql数据库,使用Sql语句就能够对数据进行处理,查找歌曲的信息,已经账户信息,返回给用户。
  4. 服务器实现了对音频文件的解析,调用第三方jar包 JAudioTager,可以对音乐文件里面的信息进行解析,从而得到专辑,艺术家,时长,等信息,返回给客户端,让客户端播放器能够正确的显示。

后面分享一下个人的所想所得~

一.服务器

  1. 首先要实现一个app,就需要自己搭建一个服务器,直接用serversocket来做服务器,也不考虑安全性什么的了,先实现以后再说,所以客户端和服务器进行的是socket通信。这些是小儿科,但是用java连接MySQL数据库是个问题,对于一个对数据库一无所知的小白来说,可是花了2天的时间去搞这个数据库,安装弄了半天,看SQL语法用了1天左右,才差不多搞懂了。接下来的1天就是学习如何使用MySQL提供的java开发包来和MySQl进行连接通信。翻阅了一些资料 jdbc 知道了它的用法,其实也蛮简单的。
  2. 连接服务器是弄好了,可是怎么把歌曲解析呢?看到的网易云音乐都是有专辑,艺术家的,这些要如何获取。百科一下了解到了音频文件是有一些特殊的地方的,音频文件讲解 ,每个mp3里面都有一些标签id3,
    第一代是idv1(version 1),基本已经无人使用,现在大多数都是idv2,idv2又分了一些版本2.1 – 2.4。这些也不用去管。借助第三方包 JAduioTagger,调用其中的方法,就可以获得这些文件的信息了。再通过jdbc,就实现了把音乐文件的信息全部导入到数据库中,这样就解决的文件提供的问题。

二.客户端(Android)

先从简单的登陆和注册界面开始,用到的都是简单的UI,没什么好说。除了记住密码的功能比较有技巧,记录密码就是根据checkBox的状态,判定是否把账户密码写到本地的sharePreference文件中,再根据里面记录的内容,判定应用开启的时候是否装载进来。还有的是,登陆和注册都涉及到了socket编程,Android里面是不允许在主线程中去运行网络连接的,所以要用到多线程。

然后是主界面,主界面要用到ListView,关于ListView就不得不吐槽了,这是一个用得最多,也是最难的一个UI,在做这个APP的时候,经常用到,吃了不少苦。使用ListView首先要有一个context,用于承载ListView的内容,还有一个ListView里面每个选项的布局,还有一个List数组,装了选项布局里面需要的内容。仿照云音乐的界面,做出类一个listView,不过下面的收藏歌单,实在是没有精力和能力去实现,所以也没多加考虑。先为本地音乐,创建一个activity,稍后再去实现它。目前优先解决搜索功能。实现标题导航,要用到actionbar,一个在平时用的很多的标题栏。创建一个搜索按钮searchView,为其注册监听器,当输入内容的时候启用另一个活动 SearchActivity显示查询的结果。

上面的那些都还是比较简单的,不过ListView以及布局等等问题,在做项目的过程中确实占用了很多的时间。搜索做完了,就轮到播放了,一个最为头疼了问题,在这个播放问题上,耗费了将近1个星期的时间,真的很不容易。
播放要怎么播放?翻了翻书,哦,用MediaPlayer,这只是简单的提供了一些方法和介绍了它的生命周期而已,并没有给予我什么启发。
首先要实现在线播放,在线播放究竟是个什么原理,起初是想直接把它下下来,然后播放,敷衍一下就算了,但是一想到,你点一首歌,用户要等半天才放,这是不是不太合理,于是就在茫茫代码中去寻找办法,网上的在线播放,很多都是直接丢一个uri然后通过调用MediaPlayer自带的serDataSourece方法进行播放,毫无技术性可言。不过终于让我发现了一份差不多符合自己想法的资料,自己好像发现了些什么。首先在线播放其实也是下载,不过它是下一点,播放一点,思路大概如下:

downloadingFile为正在下载的文件,playingFile为正在播放的文件,bufferFile为缓存文件
downloadCom为下载完成。播放要求为:文件大小>512k
getCurPos()为获取当前播放进度,getDuration()为当前MP3时长 –>为复制操作

看得出来,这里涉及到访问网络操作,所以把它丢到多线程中,但是播放要更新progressbar进度条,这又迎来了一个难题,再查资料,在子线程更新UI要用到异步机制,使用handler就可以解决这个问题。其实,这个播放条本该显示在所有活动之上的,但是当初决定了用activity,要改成fragment就要全改,也试过全改了,但是还是失败了,换成碎片以后标题栏又成了一个问题,之前在fragment和activity之间折腾了2-3天,还是改回activity,改回activity后又想着让播放条作为一个baseactivity让所有activity继承它,但是这种办法又遇到各种问题,又改了回来。跟着无意间看到Service,本身音乐播放应该是一个Service才对了,这才是一个正确的方向!!于是又接着去尝试Service,Service可以与很多活动通信,而Service始终还是一个,这就很好的解决了一个activity和另一个activity之间线程的管理问题。但是神奇的事情发生了,在Service中更新UI失败了,不过按照网上的说法应该是可以的,不过时间已经不允许我去纠结了,所以还是打回原形。到处碰壁那种辛酸真的很难受。最终发现了一个很强的东西,广播!!广播机制实现了非activity类和activity的通信,只需要一个广播就可以调用activity里面的方法, 例如更新UI!!可惜已经到了deadline了,也由于这个项目,落下了很多东西,半个月来几乎每天都在做这个项目,真的不容易。不过对Android的了解更近一层了。因为亲身实践了,亲身去跳坑,爬坑,虽然满身伤痕,不过每当实现一个功能的时候,心里是欣喜不已的,还兴冲冲的分享给身边的舍友。这种喜悦感是难以言喻的。
在做项目的时候,有查bug的痛苦,也有取得成就的喜悦,悲欢参半,收获颇丰。不过还是有很多的遗憾,如果当初知道fragment,当初知道Service,当初知道broadcast
没有人指导跳进了很多坑,不过跌跌撞撞让我明白,有很多东西不亲身去经历是不知道那是多么的难。我们平时用的那么顺手的app开发起来是那么的难。如果有下次,我可能会做得更好。


最后放上源码地址~

Android客户端
Java服务器

更多相关文章

  1. Android(安卓)Studio Lint 自动检查清除冗余资源
  2. Android关于Dex拆分(MultiDex)技术详解
  3. Android(安卓)ROM中Odex文件的作用及介绍
  4. 34.如何获取app(apk和ipa)中的资源
  5. android中在Layout布局文件中添加控件ID,在Activity中findViewByI
  6. Android: NDK编程
  7. Android(安卓)用ViewFlipper简单实现广告滚动条
  8. android指定签名的apk才能安装
  9. Android(安卓)实现视屏播放器、边播边缓存功能、外加铲屎(IJKPlay

随机推荐

  1. android 2.2 apidemos 赏析笔记 6
  2. ant android
  3. Android学习笔记(6)——Android——Login
  4. Error:Cause: buildToolsVersion is not
  5. 如何在一个声卡添加pa codec设备
  6. Android源码开发中单个模块的编译自动化
  7. Android(安卓)ConstraintLayout 降低布局
  8. Android(安卓)-- View
  9. Error while executing process /Users/x
  10. Android(安卓)使用ORMLite 操作数据库