基于安卓android的mp3播放器畢業(yè)論文_第1頁
已閱讀1頁,還剩44頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、<p><b>  畢業(yè)論文</b></p><p>  題目 基于安卓Android的MP3播放器 </p><p>  的設(shè)計(jì)與實(shí)現(xiàn) </p><p>  學(xué)生所在學(xué)院 電氣信息學(xué)院 </p><p>  專 業(yè) 軟件工程

2、 </p><p>  學(xué) 號(hào) </p><p>  學(xué) 生 姓 名 </p><p>  指 導(dǎo) 教 師 </p><p>  起 止 日 期

3、 </p><p><b>  摘要</b></p><p>  Android平臺(tái)是Google針對(duì)移動(dòng)設(shè)備所推出的一個(gè)操作平臺(tái),此平臺(tái)是以Apache開源許可的方式的進(jìn)行發(fā)布的,所以使用該系統(tǒng)是免費(fèi)的,所以開發(fā)人員能夠在該平臺(tái)上開發(fā)屬于自己的應(yīng)用。</p><p>  Android平臺(tái)是由“操作系統(tǒng)”、“中間件”、“用戶界

4、面”和“應(yīng)用程序”組成的。它采用了軟件堆層的架構(gòu)設(shè)計(jì),分為三部分,其中底層以Linux內(nèi)核工作為基礎(chǔ),只提供基本功能來處理事件;中間層包括函數(shù)庫(kù)和虛擬機(jī),負(fù)責(zé)系統(tǒng)運(yùn)行所必須的環(huán)境;最上層是各種應(yīng)用程序,包括Android系統(tǒng)自帶的通話、短信、相機(jī)等應(yīng)用;應(yīng)用軟件則由其他自由開發(fā)人員或公司自行開發(fā),然后發(fā)布到Android應(yīng)用市場(chǎng)供用戶下載。</p><p>  本文以Android開發(fā)平臺(tái)為基礎(chǔ),首先簡(jiǎn)要介紹了A

5、ndroid平臺(tái)的發(fā)展歷程、以及當(dāng)前國(guó)內(nèi)外關(guān)于音樂播放器的發(fā)展現(xiàn)狀。然后描述了Android開發(fā)平臺(tái)的開發(fā)環(huán)境的搭建。之后便對(duì)本播放器做了一個(gè)詳細(xì)的需求分析。再然后便開始描述本播放器所需使用的數(shù)據(jù)庫(kù)的設(shè)計(jì)。然后對(duì)本播放器中的所有功能界面進(jìn)行詳細(xì)介紹和功能實(shí)現(xiàn)。</p><p>  關(guān)鍵詞:Android 音樂播放器 Android平臺(tái)的開發(fā)與設(shè)計(jì)</p><p><b>  目錄

6、</b></p><p><b>  摘要I</b></p><p><b>  1. 概述1</b></p><p>  1.1 項(xiàng)目背景1</p><p>  1.2 國(guó)內(nèi)外相關(guān)研究現(xiàn)狀及發(fā)展趨勢(shì)1</p><p>  1.3 項(xiàng)目研究意義2&

7、lt;/p><p>  1.4 本文主要內(nèi)容2</p><p>  2. Android開發(fā)環(huán)境搭建3</p><p>  3. 項(xiàng)目需求分析4</p><p><b>  3.1 目的4</b></p><p>  3.2 系統(tǒng)背景4</p><p>  3.3

8、問題說明4</p><p>  3.4 系統(tǒng)范圍4</p><p>  3.5 用例圖及用例描述4</p><p>  3.6 功能摘要6</p><p>  3.7 假定與約束7</p><p>  4. 數(shù)據(jù)庫(kù)設(shè)計(jì)8</p><p>  4.1 數(shù)據(jù)庫(kù)概念設(shè)計(jì)8</p&g

9、t;<p>  4.2 數(shù)據(jù)表設(shè)計(jì)8</p><p>  4.3 數(shù)據(jù)庫(kù)的連接及操作類的編寫11</p><p>  5. 項(xiàng)目實(shí)現(xiàn)14</p><p>  5.1 歡迎界面14</p><p>  5.1.1 歡迎界面概述14</p><p>  5.1.2 歡迎界面技術(shù)分析14</p

10、><p>  5.2 播放器主界面15</p><p>  5.2.1 播放器主界面概述15</p><p>  5.2.2 主界面技術(shù)分析16</p><p>  5.3 歌曲列表17</p><p>  5.3.1 歌曲列表概述17</p><p>  5.3.2 歌曲列表實(shí)現(xiàn)17&

11、lt;/p><p>  5.4 網(wǎng)絡(luò)歌曲榜單界面18</p><p>  5.4.1網(wǎng)絡(luò)歌曲榜單界面概述18</p><p>  5.4.2 網(wǎng)絡(luò)歌曲榜單界面實(shí)現(xiàn)18</p><p>  5.5 歌曲詳情界面24</p><p>  5.5.1 歌曲詳情界面概述24</p><p>  5

12、.5.2 歌曲詳情界面實(shí)現(xiàn)25</p><p>  5.6 歌曲播放界面26</p><p>  5.6.1 歌曲播放界面概述26</p><p>  5.6.2 歌曲播放界面實(shí)現(xiàn)26</p><p>  5.6.3 歌詞顯示26</p><p>  5.7 歌曲播放29</p><p&

13、gt;  5.7.1 Service簡(jiǎn)介29</p><p>  5.7.2播放服務(wù)PlayService實(shí)現(xiàn)31</p><p>  5.8 播放控制34</p><p>  6. 系統(tǒng)測(cè)試37</p><p>  6.1 掃描音樂測(cè)試37</p><p>  6.2 播放音樂測(cè)試37</p>

14、<p>  6.3 切歌測(cè)試38</p><p>  6.4 搜索歌曲測(cè)試39</p><p><b>  總結(jié)40</b></p><p><b>  致謝41</b></p><p><b>  參考文獻(xiàn)42</b></p><p

15、><b>  1. 概述</b></p><p><b>  1.1 項(xiàng)目背景</b></p><p>  在大學(xué)前三學(xué)年的學(xué)習(xí)生活中,我學(xué)會(huì)了C++、C#、Java這三門編程語言,正因?yàn)檎莆樟司幊痰幕A(chǔ),于是在大學(xué)第四學(xué)年中,我自學(xué)了Android開發(fā),轉(zhuǎn)眼就要畢業(yè)了,我想要用我所學(xué)到的知識(shí)去完成一個(gè)基于Android的音樂播放器開發(fā)來

16、給我的大學(xué)畫上一個(gè)圓滿的句號(hào)。</p><p>  至于說為什么想到的會(huì)是一款基于Android的音樂播放器,我想說既然最近一學(xué)年在學(xué)習(xí)Android開發(fā),那就應(yīng)該用現(xiàn)階段自己掌握得最熟練的技術(shù)去開發(fā)。至于為什么是音樂播放器,那就得說說音樂在平時(shí)生活中所占的比重了。</p><p>  音樂已經(jīng)成為了人們生活中不可或缺的一部分了,閑暇無聊時(shí)聽一首安靜的慢歌、朋友聚會(huì)時(shí)在KTV高歌一曲,聽歌

17、成了習(xí)慣后,軟件開發(fā)商發(fā)現(xiàn)了商機(jī)。各式各樣的手機(jī)音樂播放器隨之被推出。誠(chéng)然,作為專業(yè)的軟件應(yīng)用開發(fā)商所開發(fā)的產(chǎn)品功能還是很強(qiáng)大的,不管是在音樂資源還是界面效果上都是很符合大眾口味的。然而秉著虛心學(xué)習(xí)的態(tài)度,都不能抑制我想要開發(fā)一款屬于自己的音樂播放器的想法。</p><p>  1.2 國(guó)內(nèi)外相關(guān)研究現(xiàn)狀及發(fā)展趨勢(shì)</p><p>  目前國(guó)內(nèi)較為流行的幾款手機(jī)端音樂播放器主要有:網(wǎng)易云

18、音樂、酷狗音樂、酷我音樂、多米音樂、蝦米音樂、天天動(dòng)聽等,這些播放器大都有海量的曲庫(kù)支持,專業(yè)的音效,炫酷的皮膚,詳細(xì)的歌曲信息、專輯信息等等。因這些播放器功能大都雷同,因本次所開發(fā)的播放器使用了百度音樂提供的開放接口,所以此處僅以百度音樂為例介紹其特點(diǎn):</p><p>  百度音樂Android版是一款專為手機(jī)定制的功能強(qiáng)大的音樂播放器,數(shù)量龐大的音樂資源提供試聽下載,權(quán)威的推薦音樂榜單,新鮮的新歌推送,智能

19、語音搜歌,登錄賬號(hào)收藏音樂,PC端和手機(jī)即可同步顯示。</p><p>  而對(duì)于國(guó)外的音樂播放器,因?yàn)榻佑|得少,這里只介紹一款。</p><p>  Beoplayer,是一款丹麥的音樂播放器,Beoplayer是一款免費(fèi)軟件,由丹麥的Bang & Olufsen公司所設(shè)計(jì)開發(fā),這是一家全球頂級(jí)的數(shù)字設(shè)備產(chǎn)品提供商,他們的產(chǎn)品設(shè)計(jì)理念是“獨(dú)特高貴”,因此其公司的產(chǎn)品一直被音樂愛好

20、者所喜愛。</p><p>  1.3 項(xiàng)目研究意義</p><p>  作為即將畢業(yè)的大學(xué)生,畢業(yè)設(shè)計(jì)是對(duì)大學(xué)學(xué)習(xí)過程中知識(shí)積累量的一次考驗(yàn),而我也想知道在大學(xué)四年期間我到底有什么收獲,所以我想要通過這次的畢業(yè)設(shè)計(jì)課題“基于Android的音樂播放器”來面對(duì)這場(chǎng)考驗(yàn),并以一個(gè)令人滿意的成績(jī)完成考驗(yàn)。</p><p>  1.4 本文主要內(nèi)容</p>

21、<p>  本次項(xiàng)目的主要研究?jī)?nèi)容是研究、分析和實(shí)現(xiàn)基于Android手機(jī)平臺(tái)的音樂播放器,具體包括以下幾個(gè)部分:</p><p> ?。?)第一章介紹項(xiàng)目背景和國(guó)內(nèi)外現(xiàn)狀</p><p> ?。?)第二章介紹Android平臺(tái)的歷史和開發(fā)環(huán)境的搭建</p><p> ?。?)第三章介紹對(duì)播放器的需求分析</p><p> ?。?/p>

22、4)第四章介紹數(shù)據(jù)庫(kù)的設(shè)計(jì)</p><p> ?。?)第五章介紹項(xiàng)目詳細(xì)的設(shè)計(jì)</p><p> ?。?)第六章介紹系統(tǒng)測(cè)試</p><p>  2. Android開發(fā)環(huán)境搭建</p><p>  Android Studio是Google推出的Android開發(fā)工具,基于IntelliJ IDEA開發(fā),類似于Eclipse等開發(fā)工具,An

23、droid Studio集成了Android開發(fā)工具用于開發(fā)和調(diào)試,并且在Android Studio的安裝包中已經(jīng)封裝了Android SDK,所以只需要安裝Java JDK 和 Android Studio即可開始Android應(yīng)用的開發(fā)。在本次開發(fā)中,所采用的開發(fā)工具及其下載地址如下表1-1所示。</p><p>  表1-1 Android開發(fā)所需工具軟件版本信息及下載地址</p><

24、p>  將上述工具下載,首先安裝Java JDK,安裝完成后配置環(huán)境變量的Path路徑和classPath路徑,打開cmd命令行工具,輸入java和javac命令查看是否配置成功。</p><p>  安裝Android Studio時(shí),若本機(jī)上并沒有Android SDK,需要勾選上Android SDK項(xiàng),在安裝完畢以后需要打開Android SDK并選在一些必須的Android API,只有這樣才能使

25、Android Studio成功編譯Android項(xiàng)目。</p><p>  完成以上步驟,便可開始Android應(yīng)用的開發(fā)了。</p><p><b>  3. 項(xiàng)目需求分析</b></p><p><b>  3.1 目的</b></p><p>  開發(fā)一款屬于自己的個(gè)性化的音樂播放器。<

26、;/p><p><b>  3.2 系統(tǒng)背景</b></p><p>  市場(chǎng)上各式各樣的播放器讓人眼花繚亂,讓人選擇起來卻無從下手。本著學(xué)習(xí)交流的心態(tài),在覺得自己有這種能力的情況下,開發(fā)一款自己的個(gè)性化的音樂播放器。</p><p><b>  3.3 問題說明</b></p><p>  音樂播放器

27、是手機(jī)必不可少的一部分,一個(gè)好的播放器能極大的增加用戶體驗(yàn),同時(shí),界面簡(jiǎn)潔,操作快捷也是一個(gè)播放器所應(yīng)具備的。本播放器系統(tǒng)流程圖如圖3.1所示。</p><p><b>  3.4 系統(tǒng)范圍</b></p><p>  音樂播放器主要為用戶提供播放音頻文件的功能,文件范圍不限于本地文件,可播放或下載網(wǎng)絡(luò)歌曲文件,適合所有喜愛音樂的人群使用。</p>&l

28、t;p>  3.5 用例圖及用例描述</p><p>  用例圖如圖3.2所示。</p><p><b>  圖3.1系統(tǒng)流程圖</b></p><p><b>  圖3.2系統(tǒng)用例圖</b></p><p>  音樂播放器的用例詳情描述如下:</p><p>  用例

29、名稱:獲取本地歌曲列表。</p><p><b>  參與者:系統(tǒng)。</b></p><p>  目標(biāo):第一次使用系統(tǒng)時(shí)系統(tǒng)自動(dòng)獲取本地符合條件歌曲的信息并存入數(shù)據(jù)庫(kù),并生成歌曲列表供用戶選擇。</p><p>  基本事件流:打開播放器,播放器在歡迎界面中判斷是否初次使用本系統(tǒng)。</p><p>  用例名稱:獲取網(wǎng)絡(luò)

30、歌曲列表。</p><p><b>  參與者:用戶。</b></p><p>  目標(biāo):獲取百度音樂提供的各類型的歌曲榜單,方便用戶收聽或下載。</p><p>  基本事件流:用戶打開“發(fā)現(xiàn)”欄目,選擇對(duì)應(yīng)的榜單,系統(tǒng)請(qǐng)求服務(wù)器返回歌曲信息并以列表形式返回給用戶。</p><p><b>  用例名稱:播放

31、。</b></p><p><b>  參與者:用戶。</b></p><p>  目標(biāo):播放用戶選定的歌曲。</p><p>  基本事件流:用戶在歌曲列表中選擇某項(xiàng),系統(tǒng)在后臺(tái)開始播放與該項(xiàng)對(duì)應(yīng)的歌曲。</p><p>  用例名稱:播放界面。</p><p><b> 

32、 參與者:用戶。</b></p><p>  目標(biāo):用戶打開對(duì)應(yīng)的歌曲的播放界面。</p><p>  基本事件流:用戶打開播放界面,系統(tǒng)顯示當(dāng)前播放歌曲的詳細(xì)信息和播放進(jìn)度。</p><p><b>  3.6 功能摘要</b></p><p>  軟件詳細(xì)功能如表3-1所示。</p><

33、;p><b>  表3-1功能摘要</b></p><p><b>  3.7 假定與約束</b></p><p>  運(yùn)行環(huán)境約束詳情如表3-2所示。</p><p>  表3-2運(yùn)行環(huán)境約束</p><p><b>  4. 數(shù)據(jù)庫(kù)設(shè)計(jì)</b></p>

34、<p>  4.1 數(shù)據(jù)庫(kù)概念設(shè)計(jì)</p><p>  根據(jù)上一章節(jié)所描述的需求分析可得到本播放器中所要使用的數(shù)據(jù)庫(kù)實(shí)體為“歌曲”,且歌曲信息實(shí)體包括歌曲id、名稱、演唱者、專輯、歌詞路徑、歌曲路徑、歌曲專輯圖片等屬性,其中歌曲id為數(shù)據(jù)表的主鍵。歌曲信息實(shí)體E-R圖如圖4.1所示。</p><p>  圖4.1 歌曲E-R圖</p><p><b&

35、gt;  4.2 數(shù)據(jù)表設(shè)計(jì)</b></p><p>  在對(duì)歌曲信息實(shí)體分析以后,就需要開始進(jìn)行數(shù)據(jù)庫(kù)表的設(shè)計(jì)了。在本播放器中,需要進(jìn)行保存在數(shù)據(jù)庫(kù)中的信息主要有“本地歌曲”、“最近下載任務(wù)”、“最愛歌曲”、“最近播放的歌曲”,而“最愛歌曲”已經(jīng)在“本地歌曲”中設(shè)置屬性判斷,無需再創(chuàng)建數(shù)據(jù)表,所以本播放器中供需使用三個(gè)表:本地歌曲表tb_local、下載任務(wù)表tb_download、最近播放表tb_

36、lately。</p><p>  本地歌曲表tb_local</p><p>  tb_local表用來負(fù)責(zé)存儲(chǔ)由用戶掃描出的音樂文件信息,信息包括由系統(tǒng)自動(dòng)生成的歌曲編號(hào),從歌曲文件中解析出的相關(guān)信息,具體字段定義見表4-1。</p><p>  表4-1 tb_local表字段</p><p>  下載任務(wù)表tb_download<

37、;/p><p>  tb_download負(fù)責(zé)保存用戶下載的歌曲信息,因歌曲下載完畢后會(huì)將信息轉(zhuǎn)存到tb_local表中,所以在tb_download中僅保存了歌曲編號(hào)信息,這個(gè)編號(hào)是從百度音樂接口獲取的歌曲編號(hào)。tb_download字段定義如表4-2所示。</p><p>  表4-2 tb_download表字段</p><p>  最近播放表tb_lately&

38、lt;/p><p>  tb_lately負(fù)責(zé)保存用戶最近播放的15首歌曲,因播放的可能會(huì)是來源于網(wǎng)絡(luò)的歌曲,所以此表中也會(huì)保存如tb_local中除卻favorite的其他信息。字段定義如表4-3所示。</p><p>  表4-3 tb_lately字段</p><p>  4.3 數(shù)據(jù)庫(kù)的連接及操作類的編寫</p><p>  在數(shù)據(jù)庫(kù)連接

39、及操作類中,主要包括對(duì)數(shù)據(jù)庫(kù)的連接及對(duì)數(shù)據(jù)庫(kù)的增刪修改操作,要連接到SQLite數(shù)據(jù)庫(kù),需要自定義工具類去繼承SQLiteOpenHelper抽象類,并實(shí)現(xiàn)其方法。此處先貼出代碼再做介紹。</p><p>  public class DataBaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME =

40、"music.db"; private static final int VERSION = 1; public DataBaseHelper(Context context){ this(context,DATABASE_NAME,null,VERSION); } public DataBaseHelper(Context context,String name,SQ

41、LiteDatabase.CursorFactory cursorFactory,int version){ super(context,name,cursorFactory,version); } @Override public void onCreate(SQLiteDatabase db) { db.exec</p><p>  在DatabaseH

42、elper類中,通過實(shí)現(xiàn)構(gòu)造方法去創(chuàng)建數(shù)據(jù)庫(kù),然后在onCreate方法中執(zhí)行創(chuàng)建表的語句,當(dāng)進(jìn)行應(yīng)用更新時(shí),再在onUpgrade方法中進(jìn)行更新數(shù)據(jù)庫(kù)的操作。然而到此還并沒有完成數(shù)據(jù)庫(kù)的連接。</p><p>  可以看到,在構(gòu)造方法中使用到了Context對(duì)象,可以想到要連接到數(shù)據(jù)庫(kù),就需要傳入這個(gè)Context對(duì)象,這就需要在Activity中對(duì)該數(shù)據(jù)庫(kù)連接對(duì)象進(jìn)行實(shí)例化了。同時(shí),為了使代碼更加簡(jiǎn)潔,此處將

43、數(shù)據(jù)庫(kù)的其他操作方法寫到另一個(gè)操作類MyDatabase中。</p><p>  在MyDatabase中,通過實(shí)例化DataBaseHelper對(duì)象dbHelper,調(diào)用其父類中的方法getWiteableDatabase獲取一個(gè)SQLiteDatabase實(shí)例,通過這個(gè)實(shí)例的方法就可以進(jìn)行數(shù)據(jù)庫(kù)的增刪修改操作了。</p><p><b>  查詢操作</b><

44、;/p><p>  在本播放器中,并沒有針對(duì)某項(xiàng)數(shù)據(jù)進(jìn)行查詢,而是查詢某表中所有的歌曲信息并保存到一個(gè)游標(biāo)集Cursor中,然后可通過此表中所擁有的字段再獲取一個(gè)信息集合List。下面代碼為根據(jù)表名稱獲取一個(gè)Cursor對(duì)象。</p><p>  public Cursor getTable(String tableName){ SQLiteDatabase db = dbHelper

45、.getReadableDatabase(); return db.query(tableName, null, null, null, null, null, null);}</p><p><b>  插入操作</b></p><p>  此處僅以向本地歌曲表中插入一項(xiàng)數(shù)據(jù)為例介紹如何插入數(shù)據(jù)。要向本地歌曲表中插入數(shù)據(jù),需要傳入一個(gè)Music對(duì)象,并獲取

46、SQLiteDatabase的可寫對(duì)象,然后執(zhí)行此對(duì)象的insert方法即可,代碼如下:</p><p>  public long insertToSong(String tableName,Music music){ SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentVal

47、ues(); values.put(MyMusicTable.SONG_ID,music.getSong_id()); values.put(MyMusicTable.URL,music.getUrl()); values.put(MyMusicTable.TITLE,music.getTitle()); values.put(MyMusicTable.ARTIST,music.getArtist());

48、 values.put(MyMusicTable.ARTIST_ID,music.getArtist_id()); values.put(MyMusicTable.ALBUM,music.getAlbum()); values.p</p><p><b>  更新操作</b></p><p>  要更新數(shù)據(jù)表中數(shù)據(jù),可直接調(diào)用SQLiteDat

49、abase對(duì)象的update方法。</p><p>  public int update(String tableName,ContentValues cv,String whereClause,String[] args){ SQLiteDatabase db = dbHelper.getWritableDatabase(); return db.update(tableName,cv,whe

50、reClause,args);}</p><p>  其中tableName表示需要更新的表的名稱,cv表示一個(gè)鍵值對(duì),其鍵為數(shù)據(jù)表中需要修改的字段,值則為更改后的值,whereClause等價(jià)于sql更新語句中的where條件,args數(shù)組表示whereClause中的“?”的值。</p><p><b>  刪除操作</b></p><p&g

51、t;  和更新操作一樣,要?jiǎng)h除某項(xiàng)數(shù)據(jù)可直接調(diào)用SQLiteDatabase對(duì)象的delete方法。</p><p>  public int delete(String table,String whereClause,String[] args){ SQLiteDatabase db = dbHelper.getWritableDatabase(); return db.delete(tabl

52、e, whereClause, args);}</p><p><b>  5. 項(xiàng)目實(shí)現(xiàn)</b></p><p>  從本章節(jié)開始,便要逐步開始播放器系統(tǒng)代碼的編寫了,這其中包括界面UI的設(shè)計(jì),各個(gè)功能的實(shí)現(xiàn)。但因代碼過多,此處便只貼出部分功能代碼,至于UI界面的設(shè)計(jì)等代碼,請(qǐng)查閱源文件。</p><p><b>  5.1 歡迎

53、界面</b></p><p>  5.1.1 歡迎界面概述</p><p>  一個(gè)應(yīng)用是很需要一個(gè)歡迎界面的,一方面給用戶表明應(yīng)用的性質(zhì),一方面又可在歡迎界面的顯示過程中去獲取應(yīng)用配置信息。在本應(yīng)用的歡迎界面SplashActivity中,通過顯示一張能夠表明主題的圖片的同時(shí),去獲取應(yīng)用的基本配置信息,如是否第一次打開應(yīng)用,歌曲的播放模式,聯(lián)網(wǎng)方式,是否打開了搖一搖切歌等信息

54、。</p><p>  5.1.2 歡迎界面技術(shù)分析</p><p>  在執(zhí)行這些可能比較耗時(shí)的操作時(shí),我們需要另開辟一個(gè)線程去執(zhí)行這些方法,在執(zhí)行完畢后,通過Handler的消息處理機(jī)制,發(fā)送消息給主線程去執(zhí)行接下來的操作。在這個(gè)另開辟的線程中執(zhí)行兩個(gè)方法,當(dāng)啟動(dòng)此應(yīng)用時(shí)即開始執(zhí)行這個(gè)StartThread線程,其流程圖如圖5.1所示。部分代碼如下:</p><p&

55、gt;  class StartThread implements Runnable{ @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }

56、 open(); }}</p><p>  圖5.1 歡迎界面流程圖</p><p>  5.2 播放器主界面</p><p>  5.2.1 播放器主界面概述</p><p>  本應(yīng)用的設(shè)計(jì)基本使用Activity和Fragment的方式進(jìn)行界面的搭配,除卻歡迎界面SplashActivity,主界面MainActivity便

57、成了其它的Fragment的父容器。此外,為方便數(shù)據(jù)的統(tǒng)一使用,SplashActivity和MainActivity均繼承自自定義的BaseActivity,減少了代碼的冗雜量。主界面上功能流程圖如圖5.2所示。</p><p>  在MainActivity中,包括三個(gè)界面:頂部的導(dǎo)航界面,底部的當(dāng)前播放信息界面,中部則是一個(gè)ViewPager組件,用于放置“我的”(LocalFragment)和“榜單”(N

58、etFragment)兩個(gè)Fragment。初始狀態(tài)下顯示“我的”界面,當(dāng)點(diǎn)擊上方的“榜單”或向左滑動(dòng)時(shí),則可顯示網(wǎng)絡(luò)歌曲推薦榜單界面。主界面效果如圖5.3所示?!鞍駟巍苯缑嫒鐖D5.4所示。</p><p>  在主界面中可看到,LocalFragment通過一個(gè)GridView組件顯示播放器記錄的部分信息,通過讀取存于數(shù)據(jù)庫(kù)中的歌曲信息,在初始化GridView設(shè)置其適配器時(shí)將數(shù)據(jù)顯示于界面上。</p&g

59、t;<p>  5.2.2 主界面技術(shù)分析</p><p>  在本應(yīng)用中,使用到了一個(gè)第三方的開源庫(kù)SlidingMenu,其效果是可展示一個(gè)側(cè)滑菜單,如常用的手機(jī)QQ的菜單樣式。通過使BaseActivity繼承其中的SlidingFragmentActivity,即可獲得這一個(gè)菜單對(duì)象,再在MainActivity的onCreate方法中初始化這個(gè)對(duì)象。效果如圖5.5所示。初始化menu的代碼

60、如下:</p><p>  private void initMenu(){ menu = getSlidingMenu(); menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN); menu.setMode(SlidingMenu.LEFT); menu.setBehindOffsetRes(R.dimen.content_

61、width); menu.setShadowDrawable(R.drawable.shadow); menu.setShadowWidthRes(R.dimen.menu_shadow); MenuFragment menuFragment = new MenuFragment(); getSupportFragmentManager().beginTransaction().replace(R.i

62、d.container_menu, menuFragment).commit();}</p><p>  圖5-2 主界面功能流程圖</p><p>  圖5.3 播放器主界面圖 圖5.4 榜單界面圖 圖5.5 菜單界面</p><p><b>  5.3 歌曲列表</b></p><p

63、>  5.3.1 歌曲列表概述</p><p>  歌曲列表主要用于顯示用戶選擇的歌單的列表,如本地音樂、我的最愛、最近播放,界面包括上方的導(dǎo)航信息和其余部分的歌曲信息列表,當(dāng)用戶點(diǎn)擊任何一首歌曲即可播放此歌曲,在每一項(xiàng)歌曲的列表項(xiàng)中都對(duì)應(yīng)有菜單選項(xiàng),用戶可根據(jù)所需對(duì)歌曲進(jìn)行移除、查看詳情等操作。歌曲列表界面上的活動(dòng)圖如圖5.6所示。</p><p>  5.3.2 歌曲列表實(shí)現(xiàn)&l

64、t;/p><p>  根據(jù)界面的樣式進(jìn)行UI設(shè)計(jì),在MusicListFragment中找出歌曲列表ListView,為了給單項(xiàng)歌曲增加菜單選項(xiàng),我們需要自定義列表項(xiàng)的布局,然后在ListView的Adapter中給每個(gè)菜單項(xiàng)添加事件。此外,為了實(shí)現(xiàn)單機(jī)歌曲項(xiàng)播放歌曲,我們需要給這個(gè)ListView添加OnItemClick事件。除此之外,為了更方便的實(shí)現(xiàn)歌曲項(xiàng)中的菜單點(diǎn)擊事件,我們需要定義一個(gè)回調(diào)接口OnLocal

65、MusicListMenuClick,并使本界面對(duì)應(yīng)的Fragment類MusicListFragment實(shí)現(xiàn)這個(gè)接口中的方法,界面截圖如5.7所示。</p><p>  圖5.6歌曲列表活動(dòng)圖 圖5.7 歌曲列表界面</p><p>  5.4 網(wǎng)絡(luò)歌曲榜單界面</p><p>  5.4.1網(wǎng)絡(luò)歌曲榜單界面概述</

66、p><p>  網(wǎng)絡(luò)歌曲榜單界面NetFragment主要用來顯示由百度音樂提供的網(wǎng)絡(luò)歌曲熱門榜單,如圖5.8所示,因其接口提供數(shù)據(jù)有限,本播放器僅提供了圖左側(cè)的的部分推薦榜單,右側(cè)則用于顯示對(duì)應(yīng)榜單的前50首歌曲,同樣,這也是播放器主界面的內(nèi)容,是主界面布局中的ViewPager的一個(gè)Fragment。</p><p>  圖5.8 網(wǎng)絡(luò)歌曲榜單</p><p>  

67、5.4.2 網(wǎng)絡(luò)歌曲榜單界面實(shí)現(xiàn)</p><p>  因?yàn)樵贜etFragment的界面中同樣是在兩側(cè)各放置一個(gè)Fragment并實(shí)現(xiàn)回調(diào)接口,所以需要在NetFragment的布局文件中為這兩個(gè)Fragment留出空間以便于放置。此處就介紹這兩個(gè)Fragment:ListMenuFragment 和ListFragment。</p><p>  榜單選項(xiàng)界面ListMenuFragmen

68、t</p><p>  此Fragment內(nèi)容相對(duì)簡(jiǎn)單,僅需要在布局中放置所需的按鈕并添加相應(yīng)的點(diǎn)擊事件即可,為提高代碼的簡(jiǎn)潔性,特為此類聲明了一個(gè)回調(diào)接口,以便在NetFragment中直接調(diào)用這些方法,接口聲明如下:</p><p>  public interface OnListMenuClickListener{ void onListMenuClick(View vie

69、w); }</p><p>  在接口的onListMenuClick方法中傳入一個(gè)View參數(shù),在NetFragment中根據(jù)此View的ID判斷是點(diǎn)擊了哪個(gè)按鈕,并執(zhí)行相應(yīng)的事件方法,方法代碼如下:</p><p>  public void onListMenuClick(View view) { if (listFragment == null)return; s

70、witch (view.getId()){ case R.id.btn_list_menu_newMusic: listFragment.updateList(GetMusicList.MUSIC_LIST_NET); break; case R.id.btn_list_menu_hotMusic: listFragment.upda

71、teList(GetMusicList.MUSIC_LIST_HOT); break; case R.id.btn_list_menu_europeMusic: listFragment.updateList(GetMusicList.MUSIC_LIST_EUROPE); break; </p><p>  

72、下面為L(zhǎng)istFragment中的updateList方法:</p><p>  public void updateList(int i) { this.type = i; if(activity.isNetworkAvailable()){ txt_loading.setVisibility(View.VISIBLE); new GetNetMusicsTask

73、().execute(i); } }</p><p>  可以看到,當(dāng)傳入一個(gè)類型參數(shù)時(shí),就會(huì)開始執(zhí)行一個(gè)GetNetMusicsTask的異步任務(wù),在此任務(wù)中會(huì)從網(wǎng)絡(luò)獲取一段xml數(shù)據(jù),并在獲取以后解析xml數(shù)據(jù)并生成一個(gè)ArrayList<QueryResult>對(duì)象,異步任務(wù)類代碼如下:</p><p>  class GetNetMusicsTask ext

74、ends AsyncTask<Integer, Integer, ArrayList<QueryResult>> { @Override protected ArrayList<QueryResult> doInBackground(Integer... params) { ArrayList<QueryResult> resultArrayList = n

75、ew ArrayList<>(); switch (params[0]) { case GetMusicList.MUSIC_LIST_NEW: GetMusicList.getMusicList(GetMusicList.MUSIC_LIST_NET, 50, 0, resultArrayList); break;

76、 case GetMusicList.MUSIC_LIST_HOT: GetM</p><p>  其中解析xml數(shù)據(jù)時(shí)用到了一種非常流行的Jsoup處理xml文檔的方式,Jsoup是一款基于Java的HTML解析器,可直接解析某個(gè)URL地址、HTML、XML文本內(nèi)容,它提供了一套非常省時(shí)省力的API,可通過DOM、CSS以及類似于JQuery的操作方法直接取出或

77、操作數(shù)據(jù)。下面是本播放器解析榜單XML文本的方法。</p><p>  public static void getMusicList(int type,int size,int offset,ArrayList<QueryResult> results){ String url = BASE_URL + "baidu.ting.billboard.billList&type

78、="+type+"&size="+size+"&offset="+offset; Document doc = null; try { doc = Jsoup.connect(url).timeout(5000).get(); Elements songs = doc.select("song_list"

79、).select("song"); if(results == null){ results = new ArrayList<>(); }else{ results.clear(); } for(Element son</p><p>  榜單歌曲列表界面ListFra

80、gment</p><p>  如同歌曲列表界面MusicListFragment,本界面也同樣是實(shí)時(shí)改變此界面中的ListView的Adapter達(dá)到改變項(xiàng)數(shù)據(jù),所以需要為L(zhǎng)istView的每個(gè)項(xiàng)設(shè)置布局并設(shè)計(jì)其項(xiàng)上的點(diǎn)擊事件,而點(diǎn)擊的目的是打開對(duì)應(yīng)歌曲的詳情頁面,代碼如下:</p><p>  listView.setOnItemClickListener(new AdapterVie

81、w.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { QueryResult result = (QueryResult) parent.getAdapter().getItem(position); activity.in

82、itDetailFragment(result.getSongID()); }});</p><p>  5.5 歌曲詳情界面</p><p>  5.5.1 歌曲詳情界面概述</p><p>  歌曲詳情界面主要用來展示用戶所選擇的歌曲的詳細(xì)信息,包括歌曲名、歌手、所在專輯、年份、歌詞等信息,若歌曲為網(wǎng)絡(luò)資源文件還可進(jìn)行下載操作。頁面效果如圖5.10所示

83、。</p><p>  圖 5.10 歌曲詳情界面</p><p>  5.5.2 歌曲詳情界面實(shí)現(xiàn)</p><p>  在歌曲詳情界面DetailFragment中,需要有一個(gè)ImageView來加載專輯圖片,多個(gè)TextView來顯示相關(guān)的文本信息,在DetailFragment中,為不影響主線程的進(jìn)行,需要另開啟異步任務(wù)去加載專輯圖片、歌詞文本等信息,在獲取歌

84、詞的異步任務(wù)中的DoInBackground方法代碼如下:</p><p>  protected Bitmap doInBackground(Long... params) { xml = GetMusicInfo.getMusicDownloadInfo(songID); if(bitrates != null){ bitrates.clear(); } bit

85、rates = GetMusicInfo.getMusicBitrateList(xml); if(bitrates == null){ music = GetMusicInfo.getMusicInfoFromPlayInterface(songID); hasBitrate = false; }else{ music = GetMusicInfo.getMusicInf

86、o(xml, bitrates.get(0)); hasBitrate = true; } Bitmap bitmap = null; if (music.getAlbumImage(</p><p>  5.6 歌曲播放界面</p><p>  5.6.1 歌曲播放界面概述</p><p>  作為一個(gè)音樂播放器,當(dāng)然需要一

87、個(gè)歌曲播放時(shí)的詳細(xì)信息界面,界面主要展示歌曲名、歌手、專輯圖片、歌詞以及對(duì)歌曲的播放控制等控件。如圖5.11所示。</p><p>  圖5.11 播放界面</p><p>  5.6.2 歌曲播放界面實(shí)現(xiàn)</p><p>  如圖5.11所示,較之前面所介紹的頁面不同的是,本頁面有更多的組件,設(shè)計(jì)更復(fù)雜的UI布局。首先在頁面頂部是一個(gè)返回按鈕,以及歌曲的名稱和歌手

88、的文本組件;在界面中部則是歌詞和歌曲專輯圖片(截圖中未顯示),當(dāng)在屏幕上左劃或右劃則交替顯示專輯圖片或歌詞;在頁面底部,則是當(dāng)前歌曲的播放控制的按鈕:播放進(jìn)度、播放模式、上一曲、播放暫停、下一曲、音量按鈕。關(guān)于更詳細(xì)的布局,請(qǐng)查看源文件中l(wèi)ayout中的fragment_play2.xml文件。</p><p>  5.6.3 歌詞顯示</p><p>  本播放器實(shí)現(xiàn)了歌曲播放時(shí)歌詞的同

89、步顯示,但由于Android官方并沒有提供類似的組件,且網(wǎng)絡(luò)上對(duì)歌曲歌詞文件的類型又各有不同,所以本播放器中采用自定義組件的方式來實(shí)現(xiàn)歌詞的顯示。</p><p>  不同的播放器可能采用不同格式的歌詞文件,在本播放器中則采用后綴為lrc的歌詞文件作為解析源頭,當(dāng)然,在解析之前我們需要先把歌詞組件定義出來,在Android中,自定義組件需要繼承所有組件的父類View或者其子類,此處則是繼承的父類View,同時(shí)實(shí)現(xiàn)

90、父類的構(gòu)造方法。</p><p>  public class Lrc extends View { private Scroller scroller; private OnLrcClickListener onLrcClickListener; public void setOnLrcClickListener(OnLrcClickListener onLrcClic

91、kListener){ this.onLrcClickListener = onLrcClickListener; } public Lrc(Context context) { super(context); scroller = new Scroller(context); init(); } public Lrc(

92、Context context, AttributeSet attrs) { super(context, attrs); scroller = ne</p><p>  因?yàn)樾枰诓季治募杏玫阶远x的Lrc組件,且需要為L(zhǎng)rc中的文本設(shè)置字體大小,所以需要在attr.xml中聲明組件的這個(gè)屬性。</p><p>  <resources>

93、 <declare-styleable name="Lrc"> <attr name="textSize" format="dimension"></attr> </declare-styleable></resources></p><p>  在Lrc中,對(duì)于一

94、個(gè)String類型的ArrayList集合,我們需要分別在onDraw方法中繪制這些String,對(duì)于當(dāng)前正在播放的歌詞我們需要定義一個(gè)畫筆hPaint,對(duì)于其他歌詞需要定義一個(gè)畫筆nPaint,當(dāng)然這兩個(gè)畫筆對(duì)象只是以不同顏色的區(qū)別來突出顯示當(dāng)前正在播放的歌詞</p><p>  hlPaint = new Paint();hlPaint.setAntiAlias(true);hlPaint.setText

95、Align(Paint.Align.CENTER); nPaint = new Paint();nPaint.setTextAlign(Paint.Align.CENTER);nPaint.setAntiAlias(true);</p><p>  在歌詞繪制時(shí),需要用到當(dāng)前組件的高度和寬度,通過實(shí)現(xiàn)父類的onSizeChanged方法可獲取。</p><p>  protected

96、 void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.width = w; this.height = h;}</p><p>  到此,則可以開始繪制歌詞了,為了不多余繪制,僅在當(dāng)前高度和寬度范圍內(nèi)繪制相應(yīng)歌詞,下面為onDraw方法中部分代

97、碼。</p><p>  canvas.drawText(listList.get(index).getLyc(), width / 2, height / 2, hlPaint);float temp = height / 2; for (int i = index - 1; i >= 0; i--) { temp = temp - 2*textSize; if (temp >

98、0) canvas.drawText(listList.get(i).getLyc(), width / 2, temp, nPaint);}temp = height / 2; for (int i = index + 1; i < listList.size(); i++) { temp = temp + 2*textSize; if(temp < height) {

99、 canvas.drawText(listList.get(i).getLyc(), width / 2, temp, nPaint); }}</p><p>  當(dāng)然,當(dāng)沒有歌詞文件時(shí),也需要繪制出相應(yīng)的提示文本。nPaint.setColor(Color.RED);nPaint.setTextSize(textSize);canvas.drawText("找不到歌詞", wi

100、dth / 2, height/2, nPaint);</p><p><b>  5.7 歌曲播放</b></p><p>  在Android中,Android提供了一個(gè)MediaPlayer來播放多媒體文件,然而為了實(shí)現(xiàn)歌曲的后臺(tái)播放,我們不能再Activity中去播放媒體文件,而是通過Service去播放。</p><p>  5.7.

101、1 Service簡(jiǎn)介</p><p>  Service是Android系統(tǒng)中的四大組件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的級(jí)別差不多,但不能自己運(yùn)行只能后臺(tái)運(yùn)行,并且可以和其他組件進(jìn)行交互。service可以在很多場(chǎng)合的應(yīng)用中使用,比如播放多媒體的時(shí)候用戶啟動(dòng)了其他Activity這個(gè)時(shí)候程序要在后臺(tái)繼續(xù)播放,比如

102、檢測(cè)SD卡上文件的變化,再或者在后臺(tái)記錄你地理信息位置的改變等等,總之服務(wù)總是藏在后臺(tái)的。</p><p>  如圖5.12所示,Service的啟動(dòng)方式有兩種,一種是通過Context對(duì)象的startService方法,另一種則是通過Context的bindService方法,因本播放器采用的是第二種方式,則僅介紹此種方式。</p><p>  從圖中可看到,通過bindService方

103、法啟動(dòng)Service的流程為:context.bindService()->onCreate()->onBind()->Servicerunning->onUnbind()->onDestroy()->Service stop</p><p>  onBind()將返回給客戶端一個(gè)IBind接口實(shí)例,IBind允許客戶端回調(diào)服務(wù)的方法,比如得到Service的實(shí)例、運(yùn)行狀態(tài)或其

104、他操作。這個(gè)時(shí)候把調(diào)用者(Context,例如Activity)會(huì)和Service綁定在一起,Context退出了,Srevice就會(huì)調(diào)用onUnbind->onDestroy相應(yīng)退出。所以調(diào)用bindService的生命周期為:onCreate --> onBind(只一次,不可多次綁定) --> onUnbind --> onDestory。在Service每一次的開啟關(guān)閉過程中,只有onStart可被多次調(diào)

105、用(通過多次startService調(diào)用),其他onCreate,onBind,onUnbind,onDestory在一個(gè)生命周期中只能被調(diào)用一次。</p><p>  圖5.10 service啟動(dòng)方式</p><p>  5.7.2 播放服務(wù)PlayService實(shí)現(xiàn)</p><p>  自定義PlayService類,繼承Service,添加一個(gè)繼承Binde

106、r的內(nèi)部類MyBinder,實(shí)現(xiàn)方法getPlayService返回當(dāng)前PlayService對(duì)象。并聲明一個(gè)MyBinder對(duì)象。</p><p>  public class PlayService extends Service {private final IBinder mBinder = new MyBinder();private final IBinder mBinder = new MyBi

107、nder();</p><p>  public class MyBinder extends Binder{ public PlayService getPlayService(){ return PlayService.this; }}}</p><p>  在BaseActivity中初始化服務(wù)連接對(duì)象ServiceConnection。&l

108、t;/p><p>  private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { PlayService.MyBinder binder = (PlayService.M

109、yBinder) service; mPlayService = binder.getPlayService(); } @Override public void onServiceDisconnected(ComponentName name) { mPlayService = null; isBind = false; }</p><

110、p><b>  };</b></p><p>  然后通過綁定服務(wù)即可調(diào)用PlayService類中的方法了。</p><p>  public void bindPlayService() { if (!isBind) { Intent intent = new Intent(this, PlayService.class);

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論