本科毕业论文(设计)诚信声明
本人郑重声明:所呈交的毕业论文(设计),题目《………基于android音乐播放器的设计……………………………》是本人在指导教师的指导下,进行研究工作所取得的成果。对本文的研究作出重要贡献的个人和集体,均已在文章以明确方式注明。除此之外,本论文(设计)不包含任何其他个人或集体已经发表或撰写过的作品成果。本人完全意识到本声明应承担的责任。
摘 要
本文说明了制作音乐播放器所用的技术,制作流程和功能介绍。
Android是一个开源的系统,它底层是基于Linux的操作系统,本论文的音乐播放器采用了Android开源系统技术,利用Java语言和Eclipse编辑工具对播放器进行编写。同时给出了详细的系统设计过程、部分界面图及主要功能运行流程图,本文还对调试过程中遇到的问题和解决方法进行了详细的讨论。
通过制作这个软件,我丰富了见闻,接触了曾经没有涉猎的技术领域。同时也系统地复习了android和java语言,可以说是收获颇丰。
该播放器能流畅的播放所有MP3文件,操作流畅,使用方便。
关键词: 界面; 服务;网络爬虫;数据库;消息机制
ABSTRACT
This paper illustrates the production technology used in the music player, production processes and functions is introduced.
Android is an open source system, its bottom is based on the Linux operating system, this paper music player USES the Android open source system technology, using the Java language and Eclipse editing tools to write player.At the same time gives a detailed system design process, part of the interface diagram and main function operation flow chart, the article also in the process of debugging problems and solving method is discussed in detail.
By making this software, I am rich experiences, once contact with no dabble in technical field.Also systematically review the android and the Java language, can be said to be fruitful.
The player can smooth play all MP3 files, smooth operation, easy to use..
Keywords: fragment and activity; service; Jsoup; SqliteDataBase;Handler
目 录
第1章 引言44
1.1 项目背景44
1.2 编写目的44
第2章 系统需求分析55
2.1 功能需求55
2.1.1 播放器基本控制需求55
2.1.2 网络歌曲需求66
2.1.2 歌词显示需求77
2.2 界面需求88
2.3 系统结构图和流程图1010
2.4 性能需求1111
2.5运行环境需求1111
第3章 Android项目介绍1212
3.1 什么是Android?1212
3.2 Android工程目录结构1313
第4章 播放器系统功能详细设计1515
4.1 播放音乐与模式1515
4.2 收藏音乐1717
4.3 音乐切换时界面状态改变1919
4.4 网络歌曲下载1919
4.5 歌词滚动显示2121
结 论2222
致 谢2828
附 录2929
第1章 引言
Android开发是当今两大手机开发之一,另一个便是IOS系统。它的优势在于广泛的用户量,开发门槛较低。而苹果系统虽然运行流畅,它有垃圾处理机制,使手机运行十几个软件都不卡;但相对开发较难,而且开发环境配置要求高,不便于平民开发。更主要是Android优点在于开放性,能接受海量的应用程序,包括一些个人自创程序软件,所以安卓的软件会比较丰富,而这点也正是IOS特点所缺少并且坚持的,只接受承认应用程序,并且非免费程序很多。
1.1 项目背景
在广大安卓手机用户的前提下,java走android路线也像web路线有很好的前途,个人立志在java领域能熟悉有关java的所有技术,然后择其一发展。此次毕业设计是一个基于android在线音乐播放器,主要用于综合android技术,熟练使用各种组件,以及一个完整android项目所碰到的难题。
随着社会迅速的发展,人们有忙不完的工作,如何在忙碌中享受生活,智能手机的普遍使得听音乐成为了一个不错的舒缓选择;在这样的背景下我制做了一款集本地和在线播放,下载和歌词显示以及播放模式于一体的基于android系统的音乐播放器。同时也锻炼了自己的专业技能,对大学四年也有一个圆满的答卷。
1.2 编写目的
作为一个毕业设计,我觉得应该把我们学过的专业知识总结出来,应用在项目中,我的android音乐播放器就是java和android这一块最好的总结,它使用eclipse adt编写java和android代码及其布局文件实现界面与数据的交互,通过观察者设计模式制作手机软件,不仅达到了锻炼自己专业技术能力的目的,而且巩固了大学课程的知识。丰富了我们见闻,也为以后找工作打下坚实的基础。
第2章 系统需求分析
2.1 功能需求
2.1.1 播放器基本控制需求
用例图表示如下:
图2.1.1 播放器基本控制功能用例图
用例名称:播放;参与者:用户;目标:播放选中列表的歌曲;
前置条件:播放器正在运行;基本事件流:点击“播放”按钮实现当前歌曲的播放。
用例名称:暂停;参与者:用户;目标:暂停当前播放的歌曲;
前置条件:播放器正在运行且正在播放;基本事件流:点击“暂停”按钮实现暂停歌曲。
用例名称:上一首;参与者:用户;目标:跳转播放当前歌曲的上一首歌曲;
前置条件:正在播放或暂停;基本事件流:点击“上一首”按钮实现上一首歌曲的播放。
用例名称:下一首;参与者:用户;目标:跳转播放当前歌曲的下一首歌曲;
前置条件:正在播放或暂停;基本事件流:点击“下一首”按钮实现下一首歌曲的播放。
2.1.2 网络歌曲需求
用例图表示如下:
图2.1.2 网络请求用例图
用例名称:歌曲下载;参与者:用户;目标:在线类别选中的歌曲;
前置条件:播放器正在运行;基本事件流:点击“下载”按钮实现对应选中歌曲的下载。
用例名称:在线播放;参与者:用户;目标:播放在线列表选中的歌曲;
前置条件:播放器正在运行;基本事件流:点击“列表中的Item”播放选中的在线歌曲。
用例名称:网上搜索;参与者:用户;目标:跳转到搜索结果显示列表;
前置条件:播放器正在运行;基本事件流:输入搜索关键字点击“搜索”按钮返回网路音乐查询结果。
2.1.2 歌词显示需求
用例图表示如下:
图2.1.2 歌词显示用例图
用例名称:歌词滚动显示;参与者:播放器系统;目标:当前播放歌词的滚动显示;
前置条件:歌曲正在播放;基本事件流:点击“播放”按钮后选中“正在播放”的tab页。
用例名称:状态量改变;参与者:播放器系统;目标:切换列表的歌曲在播放页面改变状态栏;
前置条件:播放器正在运行;基本事件流:切换歌曲时播放页面的状态图标改变。
用例名称:播放进度显示;参与者:播放器系统;目标:实时播放进度更新;
前置条件:歌曲正在播放;基本事件流:切换到“正在播放”tab页的歌曲进度条实时变化。
2.2 界面需求
一个软件除了功能外,优秀的UI界面影响着用户的使用体验。是一个能改变用户看法,增加用户数量的主要因素。这里就要我们熟练的使用Android的各种组件和界面控件,尤其是布局方式:线性布局,相对布局,帧布局,绝对布局;而线性布局又分为表格布局,网格布局等;它们的正确使用既能帮助我们日后美化界面,又能使整个软件看起来工整无暇。
我的界面做得一般,不够华丽但也很清新,这个音乐播放器包括五大界面,收藏界面,播放界面,列表界面,在线音乐界面,下载界面;采用统一的颜色格调,操作流畅,代码结构严谨,可读性强。操作也很简便,是一款适用于休闲的音乐播放软件。
界面截图如下:
这里展示了播放界面,网络界面,本地列表界面和收藏界面。
其他还有长按歌曲弹出删除分享菜单和登陆注册,
实现分享到微信,qq,微博的功能,
以及根据储存路径删除音乐文件和根据id删除mediastore的歌曲记录。
登陆注册是一个自定义的alertdialog弹出框,写入sqlitedatabase进行验证判断
2.3 系统结构图和流程图
程序开始
进入欢迎界面
本地列表界面
播放界面
网络歌曲界面
是否显示全部音乐?
是否显示全部音乐?
是否显示全部音乐?
状态不变
是否下载?
播放列表
播放列表
是否点击播放列表选项?
是否点击播放列表选项?
下载并进入下载界面
音乐播放
播放下一首/上一首
程序结束
2.4 性能需求
性能方面我做了如下优化:
1、java类的归并,归并冗长的重复的代码。
2、在对sqlite数据库做了查询优化。
3、下次进入播放器依旧保存着上次的设置和播放位置,状态量保存完好。
4、采用观察者设计模式,优化了代码结构。
2.5运行环境需求
开发工具:
Android SDK,eclipse adt22
运行环境:
在windows7,jdk1.6和android环境下使用eclipse编写代码
在adv4.4和android测试真机上调试运行
第3章 Android项目介绍
3.1 什么是Android?
1、什么是Android?这个问题从不同的角度来说有不同的答案!
在普通用户眼中,它是一个智能手机操作系统,拥有很多功能。
在android程序员眼中,它就是一个程序运行环境,许多功能都需要编写然后再添加到系统中实现运行。它也是一个开源的框架,任何人都可以自己给他添加代码,改变样式和功能。
官方介绍:Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。
Android系统的四大组件
Activity:提供可视化用户界面,一个android程序通常由多个Activity组成,它有自己的生命周期,由Android系统控制。
Service:运行在后台的一种服务程序,它很少和用户交互,因此没有可视化界面,定义一个Service很容易,只需继承Service类实现其生命周期中的方法;它必须在清单文件中注册才能使用。
BroadcastReceiver:顾名思义广播接收器,它和事件处理机制类似,只
不过事件处理机制是程序组件级别的(例如,某个按钮的单击事件),而广播事件处理机制是系统级别的。到目前为止我们可以使用Intent来启动一个程序组件,我们还可以通过使用sendBroadcast()方法来发起一个系统级别的事件广播来传递消息。我们可以在你的应用程序中实现Broadcast Receiver来监听和响应这些广播的Intent。
ContentProvider:用来保存和检索数据,并且使应用程序之间相互访问
数据成为可能。它是跨应用程序共享数据的唯一方法。
Android系统有如下的几大特性:
应用程序框架 支持组件的重用与替换
Dalvik虚拟机 专门为移动设备做了优化
内部集成浏览器 该浏览器基于开源的WebKit引擎
优化的图形库 包括2D和3D图形库,3D图形库基于OpenGL ES
SQLite 用作结构化的数据存储
多媒体支持 包括常见的音频、视频和静态印象文件格式
GSM电话,蓝牙Bluetooth,EDGE,3G and WiFi,照相机,GPS,指南针,和加速度计
丰富的开发环境 包括设备模拟器,调试工具,内存及性能分析图表,和Eclipse集成开发环境插件
3.2 Android工程目录结构
如图:
下面我来详细介绍一下它的每一个目录的作用
res目录
主要是用来存放android项目的各种资源文件,res就是resource单词的缩写。该目录几乎存放了android应用所用的全部资 源,包括:图片资源、字符串资源、颜色资源、尺寸资源,以及布局文件等。不同的文件存放在不同的目录当中,在res目录下面又有下一级目录:
layout目录主要是存放布局文件,比如主界面布局文件main.xml就在这里面。我们可以在页面中加入各种界面显示的控件。
menu目录主要是存放菜单文件,现在在android开发中使用菜单不是很频繁,比如手机很多软件在点击菜单按钮是弹出来的对话框的布局就是放在这个目录当中。
valus目录主要是存放一些数值,比如字符串资源存放在strings.xml中,color.xml可以被定义成存储颜色的代码文件;style.xml主题样式;dimens.xml存尺寸元素。
drawable目录都是用来存放图片元素的,可根据图片的大小像素决定存储位置。
assets目录
主要存放二进制资源文件或网页等等,如音乐,影视,html文件等等。
src目录
主要存放java源代码,我们一般把不同类别的java文件分开包装,增强可读性。
gen目录
android工程自动生成的文件,如R.java文件
bin目录
自动生成的二进制文件和编译后生成的文件
libs目录
存放引用的java第三方jar包
AndroidManifest.xml文件
Android工程的配置清单文件,也是整个android应用的全局描述文件。清单文件说明了android应用的名称、所使用的图标以及包含的组件等,主要包括:
1、应用程序的包名,该包名将会作为该android应用的唯一标识。
2、应用程序包含的组件,如activity、server、broadcastreceier、contentprovider等,这个就告诉我们在新建一个类继承这些组件时,我们要在清单文件中进行注册一下,否则应用程序在执行时会报错,无法找到相应的类。
3、应用程序兼容的最低版本。
4、应用程序使用系统所要获取的权限,比如你要向sd卡中写入文件就要加入:
第4章 播放器系统功能详细设计
4.1 播放音乐与模式
播放音乐是主要功能,它通过四大组件之一的service来实现的,这样做的好处就是退出界面,音乐可以后台播放,因此我们需要建立一个PlayService.java用来播放服务的类。在服务类中我们调用系统的媒体播放器android.media.MediaPlayer,在播放服务类的onCreate()方法中实例化mediaPlayer=new MediaPlayer()。然后调用它的播放,暂停,获取当前播放位置等等内置方法并加以封装修改更好的实现功能。
播放模式就简单了,只需自己设置几个播放模式常量,在调用播放方法时判断一下当前模式,在分别调用就行了,具体实现代码中有。下面是MediaPlayer的相关方法:
播放模式
private Random random=new Random();
@Override
public void onCompletion(MediaPlayer arg0) {
switch (play_mode) {
case ORDER_PLAY:
next();//顺序播放
break;
case RANDOM_PLAY:
play(random.nextInt(mp3Infos.size()));//随机播放
break;
case SINGLE_PLAY:
play(currentPosition);//单曲循环
default:
break;
}
}
由以上代码可知android服务的调用流程,先绑定onbind()后调用,以下为绑定服务的流程:
还可以startservice()。
4.2 收藏音乐
收藏音乐看起来很高端,其实无非是把点击收藏的音乐写入sqlite数据库,当我们点击收藏的“心形”图标时,会执行对新建的lovemusic.db的插入数据操作,跳转收藏页面在调用查询所有收藏歌曲的操作,判断“心形”图标的背景颜色是否为已收藏的显示的颜色,然后再次点击会执行删除当前歌曲的收藏操作。
SqliteDataBase代表一个数据库对象,它的一些方法展示如下:
public class DBhelper extends SQLiteOpenHelper{
public DBhelper(Context context, String name, CursorFactory factory,
int version) {
super(context, "lovemusic.db", null, 5);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table mymusic(id integer primary key autoincrement,"
+"title varchar(20),"+"mp3infoID varchar(20))");
}
}
PlayActivity.java部分代码
case R.id.love_music:
if(query(playService.getCurrentPosition())){
delete(playService.getCurrentPosition());
img_love.setImageResource(R.drawable.nokeep);
Toast.makeText(this, "取消收藏",1).show();
}else{
add(playService.getCurrentPosition(), mp3Infos.get(playService.getCurrentPosition()).getTitle());
img_love.setImageResource(R.drawable.keep);
Toast.makeText(this, "添加收藏",1).show();
}
private void add(int mp3id,String mp3name) {
SQLiteDatabase db=helper.getWritableDatabase();
ContentValues values=new ContentValues();
values.put("mp3infoID", mp3id+"");
values.put("title", mp3name);
db.insert("mymusic", null, values);
}
private void delete(int mp3id) {
SQLiteDatabase db=helper.getWritableDatabase();
db.delete("mymusic", "mp3infoID=?", new String[]{mp3id+""});
db.close();
}
private boolean query(int mp3id) {
SQLiteDatabase db=helper.getWritableDatabase();
Cursor cursor=db.rawQuery("select * from mymusic where mp3infoID=?",
new String[]{mp3id+""});
boolean result=cursor.moveToNext();
cursor.close();
db.close();
return result;
}
4.3 音乐切换时界面状态改变
状态改变需要调用PlayService的更新状态接口interface MusicUpdateListener中的onChange()方法,这个接口在基类BaseActivity中实现,而PlayActivity继承了这个基类,实际上所有的界面Activity都继承了这个基类用于绑定服务等,所以在PlayActivity实现了onChange()方法。在onChange()把所有状态属性的量一一根据当前播放的position进行更改,实现了对service的监听。
public void change(int position) {//状态性变量改变
Mp3Info mp3Info=mp3Infos.get(position);
setLrcView();
title.setText(mp3Info.getTitle());
end_time.setText(MediaUtils.formatTime(mp3Info.getDuration()));
if(query(playService.getCurrentPosition())){
img_love.setImageResource(R.drawable.keep);
}else {img_love.setImageResource(R.drawable.nokeep);
}
Bitmap bm=MediaUtils.getArtwork(this,mp3Info.getId(), mp3Info.getAlbumId(), true, false);
img_lyric.setImageBitmap(bm);
seekBar.setProgress(0);
seekBar.setMax((int) mp3Info.getDuration());
if(playService.isplaying()){
img_play.setImageResource(R.drawable.pause);
}else {img_play.setImageResource(R.drawable.begin);
}
switch (playService.getPlay_mode()) {
case PlayService.ORDER_PLAY:
menu.setImageResource(R.drawable.menu);
menu.setTag(PlayService.ORDER_PLAY);
break;
case PlayService.RANDOM_PLAY:
menu.setImageResource(R.drawable.shuffl);
menu.setTag(PlayService.RANDOM_PLAY);
break;
case PlayService.SINGLE_PLAY:
menu.setImageResource(R.drawable.repeat);
menu.setTag(PlayService.SINGLE_PLAY);
default:
break;
}
}
4.4 网络歌曲下载
本次软件设计采用的是百度上的音乐,其实一般情况是自己在做播放器的基础之上再做一个音乐后台,用来作为网络请求。而我觉得自己做个后台然后发出请求,这样有弊端,如音乐不全面等,我这里是利用网络爬虫Jsoup对百度音乐(http://music.baidu.com/)进行网页内容抓取,然后通过得到歌曲ID,歌名,歌手和专辑实现listview的显示布局及其通过歌曲ID和歌曲URL下载音乐。
使用Handler机制实现方法的跳转调用
具体实现代码如下:
mp3url="http://musicdata.baidu.com/data2/music/"+searchResult.getMusicId()+"/"+searchResult.getMusicId()+".mp3";
//下载歌曲
protected void downloadMusic(final SearchResult searchResult,final String url,
final Handler handler) {
mThreadPool.execute(new Runnable() {
@Override
public void run() {
File musicDirFile=new File(Environment.getExternalStorageDirectory()+Contant.DIR_MUSIC);
if(!musicDirFile.exists()){
musicDirFile.mkdirs();
}
String mp3url=url;
System.out.println("mp3url:"+mp3url);
String target=musicDirFile+"/"+searchResult.getMusicname()+".mp3";
File filetarget=new File(target);
if(filetarget.exists()){
handler.obtainMessage(MUSIC_EXISTS).sendToTarget();
return;
}else {
try {
URL url=new URL(mp3url);
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
InputStream inputStream=connection.getInputStream();
FileOutputStream fileOutputStream=new FileOutputStream(filetarget);
byte b[]=new byte[1024];
int j=0;
while((j=inputStream.read(b))!=-1){
fileOutputStream.write(b, 0, j);
}
fileOutputStream.flush();
fileOutputStream.close();
handler.obtainMessage(SUCCESS_MP3,target).sendToTarget();
} catch (Exception e) {
e.printStackTrace();
handler.obtainMessage(SUCCESS_MP3).sendToTarget();
}
}
}
});
}
既然说到了网页爬虫jsoup,我还使用了它调用百度音乐的搜索引擎来获取百度音乐的热歌榜和按输入的关键字进行搜索;
SearchUtil的主要部分代码:
//Jsoup请求网络数据
private ArrayList<SearchResult> getMusicList(final String key,final int page){
final String start=String.valueOf((page-1)*SIZE);
Document doc=Jsoup.connect(URL).data("key",key,"start",start,"size",String.valueOf(SIZE))
.userAgent(Contant.USER_AGENT).timeout(60*1000).get();
Elements songTitles=doc.select("div.song-item.clearfix");
Elements songInfos;
ArrayList<SearchResult>searchResults=new ArrayList<SearchResult>();
TAG:
for(Element song:songTitles){
songInfos=song.getElementsByTag("a");
SearchResult searchResult=new SearchResult();
for(Element info:songInfos){
//歌曲链接
if(info.attr("href").startsWith("/song")){
searchResult.setMusicname(info.text());
searchResult.setUrl(info.attr("href"));
searchResult.setMusicId(info.attr("href").substring(info.attr("href").lastIndexOf("/")+1));
System.out.println(info.attr("href").substring(info.attr("href").lastIndexOf("/")+1));
}
//歌手链接
if(info.attr("href").startsWith("/data")){
searchResult.setArtist(info.text());
}
//专辑链接
if(info.attr("href").startsWith("/album")){
searchResult.setAlbum(info.text().replaceAll("<|>",""));
}
}
searchResults.add(searchResult);
}
return searchResults;
}
4.5 歌词滚动显示
歌词滚动显示主要原理就是一个滚动的TextView控件,先通过路径和歌名读取歌词文件,写入流,然后解析歌词格式,把歌词前的时间作为播放某一句的时间,然后把当前的播放的那行设为高亮等等,部分代码如下:
LyricView.java
// 绘图歌词
onDraw(Canvas canvas) {
super.onDraw(canvas);
currentPaint.setColor(Color.YELLOW);
notCurrentPaint.setColor(Color.WHITE);
currentPaint.setTextSize(TEXT_SIZE); // 设置字体大小
currentPaint.setTypeface(Typeface.SERIF); // 设置字体样式
notCurrentPaint.setTextSize(textSize);
notCurrentPaint.setTypeface(Typeface.DEFAULT);
setText("");
canvas.drawText(mLrcList.get(index).getLrcStr(), width / 2,
height / 2, currentPaint);
float tempY = height / 2;
// 画出本句之前句
for (int i = index - 1; i >= 0; i--) {
// 向上推移
tempY = tempY - textHeight;
canvas.drawText(mLrcList.get(i).getLrcStr(), width / 2, tempY,
notCurrentPaint);
}
tempY = height / 2;
// 画出本句之后的句子
for (int i = index + 1; i < mLrcList.size(); i++) {
// 往下推移
tempY = tempY + textHeight;
canvas.drawText(mLrcList.get(i).getLrcStr(), width / 2, tempY,
notCurrentPaint);
}
}
}
处理歌词的方法:
parseLrc(InputStream inputStream) {
//解析歌词时间
timeStr(String timeStr)
LyricContent.java(用来存放歌词的实体类)
歌词部分我借鉴了网上的一些资料,其实在github网上有这样歌词的demo,我下载下来仿照制作了自己的歌词显示,由于我使用eclipse adt开发工具无法像android studio那样直接引入三方插件为自己所用,只能自己看资料理解它的类的使用。
结 论
通过本次毕业设计,让我对java基础知识进行了巩固和提升,对android体系有了更加深刻的认识,对程序设计模式和面向对象编程思想了解得更加透彻。下面来说说我制作这个应用的历程和心得吧!
历程:
的确,做这个东西花费了我一个寒假的时间,起初只是实现了基本的播放和下一首的功能,这些书上就有介绍,界面没有美化,光秃秃的几个按钮,歌曲的路径还得自己写,慢慢的我找到了mediaplayer这个自带的android媒体库,可以通过它得到url,这让我又方便了许多,起码没必要自己输入歌曲路径了。启动Service一个Service有两种方法:一种是startService (Intent);另外一种是:bindService (Intent);
第一种启动方式,适用于Service独立完成任务,例如说一个下载,如果不需要暂停或者取消的话,可以这样来做。但是,我们这是音乐播放应用,把MediaPlayer放在Service中执行播放,这样的方式很难有暂停等交互。(其实也可以这样做,例如每次交互操作都用startService来做,通过Intent把暂停等命令出入进去,进度条也可以通过广播来发送出去,但是这样做,感觉很丑陋,肯定不是常规的高效做法);第二种启动方式,可以在onServiceConnected中,获得一个Service对象(可能不是一个Service对象,至少是一个可以接触Service内部操作的句柄)。这样,便可以轻松操作播放和接收进度通知。但是这种方式有弊端,一旦与之绑定的context退出,则绑定接触,Service也会被回收(但是不会执行onDestory方法);那么是不是就只是简单用第二种启动方式?当然不是这样,这两种方式并不冲突,而且十分适用于音乐播放类的应用。
接着,我使用了listview实现了歌曲列表,这个比较简单,以前学过也使用过;然而在tab布局时发生了奇怪的事情,TabActivity不能像往常一样调用PlayService服务,我找了很多地方,由于我开始并不知道是TabActivity的问题以为是PlayService在绑定服务时ServiceConnection连不上,后来才一步步排除这些可能,应该是TabActivity的问题,在一个微博上看到一个人的解说,它与普通的Activity有所不同:
bindservice=this.getApplicationContext().bindService(intent,serviceConnection,Context.BIND_AUTO_CREATE);Log.i("bind", "服务绑定");//TabActivity的问题,bindservice要加getapplicationcontext。这个问题让我纠结了好几天,我问的好友都说真是个奇葩的问题,算是学习了。
接下来做的是收藏音乐的功能,主要是sqlite这块,基本无错,增删查都行,另外就是调用listview把数据设置进去就行了,就模仿本地列表就行了。
然后我发现一个问题,我所做的这些操作是成功了,但设计界面时,它的状态量并没有改变,例如我点击播放后,那个播放按钮并没有显示暂停图标,收藏音乐并没有把心形图标显示为红色,也就是状态没随之改变,但收藏列表已经添加了。接下来我就在播放服务类实现了监听,在基类实现调用并让所有Activity继承BaseActiviy以便实时改变状态,我看到教程中使用了观察者设计模式,也设计了两个方法,一个是publish方法,打算用于实时的变量操作,如进度条等等;另一个change方法实现对状态性变量的判断改变操作。如收藏界面图标改变,播放按钮图片切换等等。
(5) 至此,本地的功能基本上就完成了,接着我着手制作网上音乐播放和下载展示。由于时间有限以及完美性要求,我直接使用百度上的音乐。这里就要隆重的介绍一个爬虫Jsoup类了,通过网上关于它的使用教程,我成功的得到了百度音乐的热歌榜单,并用同样的listview展示出来,关于音乐搜索,也是在网页得到那个搜索框实现了搜索功能,这样整个百度就相当于这个播放器的后台,搜索的音乐也越来越广泛了。如果是自己建的后台肯定就不能随心所欲的搜索了。
后来是下载功能,本来下载也可以通过Jsoup获取百度音乐的Url,后来百度做了版权,把url给隐藏起来,所以我曾一度迷茫,到处找下载百度音乐的链接,终于功夫不负有心人,在一个论坛我找到一个百度音乐的外部链接,测试可以使用后我修改了代码,直接得到音乐的ID再拼接外链地址实现了下载功能。不过我想不久的将来,百度也会修改外链,或停止外链,到时候就要大神去攻破难题了。具体下载就是对文件的读写,这个没什么好提的。
(7) 最终章,歌词滚动显示,这我真的不会动手,百度了一个demo自己修改代码才实现的;具体是先写一个滚动的textview,然后写一个歌词实体类LyricContent生成get和set方法用来存放取到的歌词,最后写一个读取歌词文件和解析歌词文件的方法,以流的形式每隔0.1秒读取一行,设置前行,当前行和下一行的样式。貌似就是这样就能够实现歌词的滚动高亮显示。具体有代码注释。
我的心得:
这次毕业设计,我很荣幸的完成了这次任务,虽然困难重重,但也收获颇丰,总而言之,万事开头难,一件事只要你想做并动手,其实就成功了一半,刚开始的时候还感觉这个任务难以完成,做到后来就感觉上手了,代码流程都弄清楚了,编写起来就简单多了。作为一个当代的大学生,我们要有紧迫感;同时也要有足够的自信,这点我是有点不足,IT专业意味着我们以后能拿高薪,相对的这个IT领域只有技术才能立足。技术是永远在不断的成熟,不断地更替,尤其是IT;我主学的是java语言,这种语言才出现几十年,面向对象语言如今非常流行,这我们不用担心会被淘汰,然而一些框架却很容易被另外优秀的给取代。所以无论是javaweb还是android方向,都需要精湛的java基础,特别是android,我曾经看到过一些安卓游戏源码,基本上游戏的规则等等都是java代码写的,而android的一些组件和UI元素只不过用来通信、跳转以及界面美化。只有将java精通,再来深入android系统,才能更好地写出令人折服的程序。
另外程序设计模式是另一个组成重要部分,这个音乐播放器,我采用的是“观察者设计模式”;将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。另外这次毕业设计我学到了”基类“这个名词,我对它的理解就是把大部分类都具有属性或都要用到的方法写入基类然后继承它,减少重复冗余的代码,增强代码的可读性。
在这次应用制作中我还使用到了android的一些组件,Activity就不说了,有界面展示基本都要用到;service有一个音乐播放的服务类,其实广播也可以办到但那样不符合一般播放器的理念;intent在页面跳转和传参用到了,另外还有SqliteDataBase小型数据库的CRUD操作在做收藏时也必不可少。界面UI组件的话有ListView,TextView,EditText,ImageView,SeekBar等,布局方式也用了两种LinearLayout,RelativeLayout。这些android的东西我学过也用过,但没有把他们综合到一个应用里面来,现在终于完整的开发出一个基本功能都能实现的应用了。另外这次设计我另一个巨大的收获就是Jsoup的使用,以前就听说过各种爬虫软件,感觉很可怕,现在自己用到爬虫Jsoup就感觉更加可怕,不是它本身可怕,而是它那强大的功能,简直是破解网站信息的最佳神器。它需要引入相应的lib包,通过document得到网页信息,然后一步步根据它封装的方法解析网页,从中得到有用的数据,我的音乐下载链接就是通过它得到的。在线播放这根本不需要怎么做,我直接用一个webview就完事了,看着离成功越来越近,我做的也缓慢下来,开始进行优化,最终成形。
做任何事都要勇于探索,即便遇到前所未有的难题也要乐于思索,不能半途而废,相信水滴石穿,也许井水就差你那一锄头就会喷涌而出。我也曾遇到过几天也解决不了的程序难题,在不断地调试和百度中,终于找到了问题所在,接着解决它不就分分钟吗?可以想象,当你解决成千上万的程序bug后,那些bug就是一份我们程序员梦寐以求的财富。记住,IT界没有解决不了的bug,只有解决不了bug的人。我们这个行业主要是看开发经验年数,为什么?熟能生巧,bug遇到得多了编程就没什么问题了。相应的基础也滚瓜烂熟,什么类,什么jar包是干什么的都知道。任何一件事情都要抱着谨慎的心态去做,不要因为简单而过于轻浮,也不要因为复杂而轻易放弃。只有不断取得进步才能拥有做这件事的意义。另外获取事务的途径也要学会走正当的捷径,比如我们没必要死记硬背那些帮助文档,因为那是用来查的,我们只需里面大概知道有哪些东西,至于具体的用法再去帮助文档查,就像我们不需要知道计算机是怎么构成的,我们是用户,我们只需要会使用它就行了。但这并不是说我们啥也不干,基础还是要懂,概念还是要有;程序员做出来的软件最终还是提供给用户使用,所以我们必须一面和电脑打交道,一面跟用户沟通,这就意味着我们担任着人机交互的翻译官。深入了解计算机和编程工具的原理,以及各种语言,使之能够识别并把人们的需求意愿转达给它,让它帮助人们处理各种重复计算复杂的难题。计算机只识别1和0,我们用编程语言向计算机展示我们的意思,从而达到人机交互。
Android内核就是基于linux系统,虽然官方并没有规定它专门用java编程,但实际上大都使用的就是java语言,它使用了jdk的大部分类,另外添加android的lib实现java对android组件操控,这样就形成了一种类java语言。因为我也会javaweb开发,感觉Android也类似于javaweb,都可以写UI布局,可以用java操控界面组件。只是android编程需要java语言更加精深。
参考文献
李刚.疯狂Android讲义[M]. 北京:电子工业出版社,2013:25-42.
赵亮,张维.基于Android技术的界面设计与研究[D].徐州建筑职业技术学院,2001,10(2):33-40.
刘玉平. Java输入输出流及在网站开发中的应用探讨[J]. 郴州市科技局,2009,(18):35-49.
韩超. Android经典应用程序开发[J] . 人力资源出版社,2011:5-18.
熊刚. 基于.Android的智能手机的设计与实现[D]. 武汉理工大学, 2010.
刘卫国,姚昱禹. Android的架构与应用开发研究[J] . 中南大学:信息科学 与工程学院 计算机系统应用 2008-11:110-112.
靳岩,姚尚朗.Android 发入门与实践[D].人民邮电出版补, 2009,59
刘平. Android手机访问服务器的一种数据交互方法[J] . 西安财经学院 网络 与现在教育技术中心,2010-09:96-102.
Bruce Eckel .Thinking in java(java 编程思想)第四版.北京:机械工业出版社, 2011
马志强.基于.Android平台即时通信系统的设计与实现[D]. 北京交通大学 2009.
王向辉,张国印,赖明珠. Android应用程序开发第二版 北京:清华大学出版社数字出版网站2012
柯元旦. Android内核剖析[M]. 北京:电子工业出版社, 2011:59-70.
BruceEckel著 陈昊鹏 译 .Java编程思想(第四版)机械工业出版社 2010
传智播客高教资源研发部.android移动应用基础教程中国铁道出版社十二五规划教材
Xin Chen,Songwei Ma,Bingli Guo,Yan Wang,Juhao Li,Zhangyuan Chen,Yongqi He.A novel fragmentation-aware spectrum allocation algorithm in flexible bandwidth optical networks[J]. Optical Switching and Networking,2014(12):6-22.
陈璟,陈平华,李文亮. Android内核分析[J]. 广东工业大学计算机学院 实践与经验,2009:112-115.
致 谢
本设计在文志诚老师的悉心指导和严格考查下业已完成,从课题选择,方案思路论证到具体设计都无不凝聚着导师的心血和我努力的汗水,再次表示对老师崇高的敬意。不积跬步无以至千里,不积小流无以成江海,本设计能够完成也归功于各位任课老师的认真负责,使我能够很好的掌握和运用专业知识,这些在我的设计中体现得淋漓尽致。
两个月的刻苦设计编写代码,如今终于达到预期的效果,基本功能都有了,但也有一些缺陷,前面都有提到,但在虚荣心涌上之时,我又会默默安慰自己:做一件事情,不必过于在乎最终的结果,可贵的是过程中的收获,真正的去做成一件大的正事。
四年的大学生活就快走入尾声,这将会成为步入社会之前最后也是最值得眷恋,让人流连忘返的一段回忆,从这里走出我们将踏上新的征程,把所学所得应用到实际工作中去。感谢四年陪伴我的小伙伴们,希望大家以后能事事如意,工作顺利。
附 录
播放器源码