




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
.引言1.1選題目的及意義隨著科技的進(jìn)步,通信技術(shù)的迅速發(fā)展,手機(jī)的功能越來越多,對我們?nèi)粘I畹挠绊懸彩窃絹碓酱?,甚至有著超越傳統(tǒng)PC的趨勢。現(xiàn)如今的手機(jī)不再是只能撥打電話,發(fā)送短信的通訊工具,它還可以上網(wǎng),玩游戲,播放音頻、視頻,甚至編輯文檔等等。隨著手機(jī)的發(fā)展,各種手機(jī)播放器也緊跟著發(fā)展起來,但是目前很多播放器一味追求外觀花哨,功能龐大,對用戶的手機(jī)造成了很多資源浪費(fèi)。比如CPU,內(nèi)存等的占用率過高,在用戶需要多任務(wù)操作時(shí),就會(huì)有不小的影響,給用戶帶來了許多不便。對于大多數(shù)普通用戶用來,許多功能是用不上的,形同虛設(shè)。所以開發(fā)一款實(shí)用并且小巧玲瓏的手機(jī)音樂播放軟件是具有良好的市場和應(yīng)用前景的。當(dāng)今時(shí)代是移動(dòng)互聯(lián)網(wǎng)時(shí)代,360董事長周鴻祎曾說過,“誰輸在了移動(dòng)互聯(lián)網(wǎng)上,誰就輸了未來,誰抓住了移動(dòng)互聯(lián)網(wǎng)的機(jī)會(huì),誰就有了未來成功的門票?!弊阋娨苿?dòng)互聯(lián)網(wǎng)的重要性。所以本課題致力于開發(fā)一款基于Android平臺的手機(jī)音樂播放器,抓住移動(dòng)互聯(lián)網(wǎng)的機(jī)會(huì),以此學(xué)習(xí)并掌握Android移動(dòng)平臺應(yīng)用開發(fā)的技能。1.2國內(nèi)外的研究現(xiàn)狀目前國內(nèi)的Android開發(fā)還是主要以應(yīng)用開發(fā)為主,主要分成3類:為企業(yè)開發(fā)應(yīng)用、開發(fā)通用應(yīng)用以及游戲開發(fā)。第一類開發(fā)者一般身處規(guī)模較大的公司,除了根據(jù)需求對系統(tǒng)進(jìn)行定制外,更多的工作在于為這些系統(tǒng)編寫定制的應(yīng)用。第二類開發(fā)者一般處于創(chuàng)業(yè)型公司或者是獨(dú)立開發(fā)者,主要靠為國外公司進(jìn)行外包開發(fā)和通過Google的移動(dòng)廣告點(diǎn)擊分成。理論上是通過付費(fèi)下載的形式來盈利,現(xiàn)在國內(nèi)鮮見成功者。第三類開發(fā)者,目前和第二類開發(fā)者類似[1]。1.3可行性分析由于手機(jī)市場的龐大,手機(jī)操作系統(tǒng)也是各式各樣。其中比較有代表性的手機(jī)操作系統(tǒng)有四個(gè),Windowsmobile,Symbian,IOS,以及谷歌的Android操作系統(tǒng)。相比于Symbian的日落西山,以及蘋果的封閉、WindowsPhone的前途未卜,Android無疑代表了當(dāng)前行業(yè)發(fā)展的主流趨勢:開放平臺取代了封閉平臺。讓參與者均能通過自己的努力而獲益[1]。Android是Google公司歷經(jīng)數(shù)年和投資數(shù)億美元開發(fā)出來并于2007年11月5日公布的智能手機(jī)操作系統(tǒng)。隨著各大移動(dòng)終端生產(chǎn)商大力開發(fā)和生產(chǎn)基于Android的移動(dòng)智能設(shè)備,Android迅速得到業(yè)界和社會(huì)的認(rèn)可,并成為整個(gè)產(chǎn)業(yè)的熱點(diǎn),基于Android平臺的各類人才逐漸成為各大企業(yè)競相爭奪的焦點(diǎn)。而且Android是一個(gè)開放的系統(tǒng),不管是企業(yè)還是個(gè)人都可以參與來表達(dá)自己的創(chuàng)意和想法。Google公司于2007年11月5日宣布組建的一個(gè)全球性的聯(lián)盟組織——開放手機(jī)聯(lián)盟,Google、中國移動(dòng)、T-Mobile、三星、高通、德州儀器等領(lǐng)軍企業(yè)將通過開放手機(jī)聯(lián)盟攜手開發(fā)Android。Android系統(tǒng)采用了軟件堆層(softwarestack,又名以軟件疊層)的架構(gòu),主要分為三部分。底層Linux內(nèi)核只提供基本功能;其他的應(yīng)用軟件則由各公司自行開發(fā),部分程序以Java編寫。本課題應(yīng)用基于Android框架開發(fā),可以在eclipse中安裝Android開發(fā)工具,使用Android模擬器,也可以使用任意Android終端。模擬器和真正的Android手機(jī)沒有太大區(qū)別,人們對手機(jī)操作早已熟悉。操作起來相當(dāng)方便。綜合以上幾方面,該應(yīng)用的開發(fā)具有很高的可行性。2.Android項(xiàng)目介紹2.1什么是Android2.1.1Android簡介Android一詞最先出現(xiàn)于法國作家利爾亞當(dāng)(AugusteVilliersdel'Isle-Adam)于1886年發(fā)表的科幻小說《未來夏娃》(L'èvefuture)中,作者將外表像人的機(jī)器起名為Android。據(jù)說Android系統(tǒng)之父安迪·魯賓(AndyRubin)是效仿LinusTorvalds命名Linux系統(tǒng)的方式來給Android系統(tǒng)命名的。[2]同時(shí),它也是Google于2007年11月5日宣布的基于Linux平臺的開源手機(jī)操作系統(tǒng)的名稱。該平臺由操作系統(tǒng)、中間件、用戶界面和應(yīng)用軟件組成,是首個(gè)為移動(dòng)終端打造的真正開放和完整的軟件平臺和操作系統(tǒng)[3]。Android系統(tǒng)是一款基于Linux內(nèi)核的綜合系統(tǒng)平臺,集合了應(yīng)用程序、應(yīng)用程序框架、系統(tǒng)核心庫、Dalvik虛擬機(jī)、Linux內(nèi)核等一系統(tǒng)功能模塊。采用了軟件堆層的架構(gòu),由三個(gè)部分組成。底層以Linux為操作系統(tǒng)內(nèi)核,提供進(jìn)程管理、存儲管理等基本功能[4]。其他各公司自行開發(fā)市場需求的應(yīng)用軟件,部分程序以java編寫。Android系統(tǒng)最初并不是由Google公司研發(fā)出來的,而是由安迪·魯賓帶領(lǐng)的團(tuán)隊(duì)創(chuàng)立的。他曾創(chuàng)立兩個(gè)操作系統(tǒng)公司,Android為其中之一。Google公司于2005收購了Android系統(tǒng),安迪·魯賓則成為其工程部副總裁,繼續(xù)負(fù)責(zé)Android項(xiàng)目的研發(fā)工作。從此,Android系統(tǒng)踏上了飛速發(fā)展的道路。2007年11月5日,Google公司正式向外界展示了Android系統(tǒng),并在當(dāng)天宣布建立一個(gè)全球性的聯(lián)盟組織——開放手機(jī)聯(lián)盟(OpenHandsetAlliance)。該組織由34家手機(jī)制造商、軟件開發(fā)商、電信運(yùn)營商以及芯片制造商組成,支持Google發(fā)布的手機(jī)操作系統(tǒng)以及應(yīng)用軟件,并共同開發(fā)Android系統(tǒng)的開放源代碼[5]。隨著時(shí)間的推移,Android系統(tǒng)逐漸壯大,目前在智能手機(jī)和平板電腦市場均處于霸主地位。采用Android系統(tǒng)主要廠商包括HTC、SAMSUNG、LG、魅族、華為、中興、聯(lián)想、小米等。目前最新SDK版本為Android4.4。2.1.2Android的基本框架Android的系統(tǒng)架構(gòu)和其操作系統(tǒng)一樣,采用了分層的架構(gòu)。從架構(gòu)圖看,Android分為四個(gè)層,從高層到低層分別是應(yīng)用程序?qū)印?yīng)用程序框架層、系統(tǒng)運(yùn)行庫層和Linux內(nèi)核層。圖1Android系統(tǒng)架構(gòu)圖(1)應(yīng)用程序?qū)覣ndroid不僅是操作系統(tǒng),也包含了許多的應(yīng)用程序。其中包括諸如SMS短消息程序,email客戶端,地圖,瀏覽器,聯(lián)系人管理,日歷程序等等。所有應(yīng)用程序都是使用JAVA語言編寫的,并且可以被開發(fā)人員所開發(fā)的其他程序替代。(2)應(yīng)用程序框架層應(yīng)用程序框架層是Android應(yīng)用開發(fā)的基礎(chǔ),允許開發(fā)人員完全訪問核心應(yīng)用程序所使用的API框架。該層簡化了組件的重用,開發(fā)人員可以直接使用其提供的組件進(jìn)行快速的應(yīng)用程序開發(fā),也可以通過繼承實(shí)現(xiàn)個(gè)性化的拓展。主要包括如下組件:視圖系統(tǒng)(ViewSystem)、內(nèi)容提供者(ContentProviders)、資源管理器(ResourceManager)、通知管理器(NotificationManager)、活動(dòng)類管理器(ActivityManager)、窗口管理器(WindowManager)、電話管理器(TelephonyManager)等等。(3)系統(tǒng)運(yùn)行庫層系統(tǒng)運(yùn)行庫層主要分為系統(tǒng)庫和Android運(yùn)行時(shí)環(huán)境兩部分。eq\o\ac(○,1)系統(tǒng)庫系統(tǒng)庫是應(yīng)用程序框架的支撐,同時(shí)也是連接應(yīng)用程序框架層與Linux內(nèi)核層的重要紐帶,主要包含以下幾部分:執(zhí)行多個(gè)應(yīng)用時(shí),管理顯示與存取操作之間互動(dòng),也負(fù)責(zé)2D、3D繪圖顯示合成的SurfaceManager、多媒體庫MediaFramework、關(guān)系型數(shù)據(jù)庫引擎SQLite、繪圖函數(shù)庫OpenGLEs、提供點(diǎn)陣字與向量字描繪與顯示的FreeType、瀏覽器引擎WebKit、底層2D圖形渲染引擎SGL、安全認(rèn)證SSL、C系統(tǒng)庫函數(shù)Libc。eq\o\ac(○,2)Android運(yùn)行時(shí)環(huán)境Android應(yīng)用程序在Android運(yùn)行時(shí)環(huán)境中執(zhí)行,運(yùn)行時(shí)環(huán)境可以分為核心庫和Dalvik虛擬機(jī)兩部分。核心庫提供了Java語言中所封裝的大多數(shù)類和方法。如android.os、、android.media等。Dalvik虛擬機(jī)是Google公司自己設(shè)計(jì)的用于Android平臺的Java虛擬機(jī),主要有以下幾個(gè)特征:所有類文件編譯完成的CLASS文件都會(huì)整合到一個(gè)DEX文件中,減少了文件大小,方便I/O操作,也提高了類的查找速度;每一個(gè)Android應(yīng)用程序都運(yùn)行在一個(gè)相對獨(dú)立的Dalvik虛擬機(jī)實(shí)例里,而每一個(gè)虛擬機(jī)實(shí)例都是一個(gè)獨(dú)立的進(jìn)程空間;Dalvik虛擬機(jī)是基于寄存器的,雖然硬件通用性比基于堆棧的虛擬機(jī)要差一些,但是代碼的執(zhí)行效率卻更勝一籌,基于寄存器的虛擬機(jī)可以更有效地減少冗余指令的分發(fā)和減少內(nèi)在的讀寫訪問。(4)Linux內(nèi)核層Android的核心系統(tǒng)服務(wù)依賴于Linux2.6內(nèi)核,如安全性,網(wǎng)絡(luò)協(xié)議棧,內(nèi)存管理,驅(qū)動(dòng)模型和進(jìn)程管理。Linux內(nèi)核也同時(shí)作為硬件和軟件堆棧之間的硬件抽象層。同所有Linux內(nèi)核一樣,Android內(nèi)核是介于硬件層和軟件組之間的一個(gè)抽象層次。2.1.3Android系統(tǒng)的四大組件Android開發(fā)四大組件分別是:Activity活動(dòng):用于表現(xiàn)功能。ContentProvider內(nèi)容提供者:支持在多個(gè)應(yīng)用中存儲和讀取數(shù)據(jù)。BroadcastReceiver廣播接收器:用于接收廣播。Service服務(wù):后臺運(yùn)行服務(wù),不提供界面。eq\o\ac(○,1)ActivityActivity是所有程序的根本,所有程序的流程都運(yùn)行在Activity之中,Activity可以算是開發(fā)者遇到的最頻繁,也是Android當(dāng)中最基本的模塊之一。一個(gè)Activity通常就是一個(gè)單獨(dú)的屏幕,它上面可以顯示一些控件也可以監(jiān)聽并處理用戶的事件做出響應(yīng)。一般一個(gè)Android應(yīng)用是由多個(gè)Activity組成的。多個(gè)Activity之間可以進(jìn)行相互跳轉(zhuǎn)和通信,主要是通過Intent(意圖)來實(shí)現(xiàn)的。eq\o\ac(○,2)ContentProvider在Android中,數(shù)據(jù)的保護(hù)是很嚴(yán)密的,除了放在SD卡中的數(shù)據(jù),一個(gè)應(yīng)用所持有的數(shù)據(jù)庫、文件等內(nèi)容,都是不允許其他應(yīng)用直接訪問的。如果一個(gè)應(yīng)用需要使用其他應(yīng)用的文件要怎么辦呢?這個(gè)時(shí)候就要用到ContentProvider了。應(yīng)用想對外提供的數(shù)據(jù),可以通過派生ContentProvider類,封裝成一枚ContentProvider,每個(gè)ContentProvider都用一個(gè)uri作為獨(dú)立的標(biāo)識,形如:content://com.xxxxx。這樣,其他應(yīng)用就可以通過ContentResolver類(見ContentProviderAccessApp例子)從該內(nèi)容提供者中獲取或存入數(shù)據(jù)(相當(dāng)于在應(yīng)用外包了一層殼)。eq\o\ac(○,3)BroadcastReceiver在Android中,Broadcast是一種廣泛運(yùn)用的在應(yīng)用程序之間傳輸信息的機(jī)制。而BroadcastReceiver是對發(fā)送出來的Broadcast進(jìn)行過濾接受并響應(yīng)的一類組件。應(yīng)用可以使用它對外部事件進(jìn)行過濾只對感興趣的外部事件(如當(dāng)電話呼入時(shí),或者數(shù)據(jù)網(wǎng)絡(luò)可用時(shí))進(jìn)行接收并做出響應(yīng)。廣播接收器沒有用戶界面。然而,它們可以啟動(dòng)一個(gè)activity或serice來響應(yīng)它們收到的信息,或者用NotificationManager來通知用戶。通知可以有很多種方式來吸引用戶注意力,一般來說是在狀態(tài)欄上放一個(gè)持久圖標(biāo),用戶可以打開它獲取消息。同時(shí),應(yīng)用還可以通過使用Context.sendBroadcast()將它們自己的IntentBroadcasts廣播給其他應(yīng)用程序。eq\o\ac(○,4)Service相信熟悉Windows系統(tǒng)的人都知道Windows有許多的服務(wù),Android中的服務(wù)與Windows中的服務(wù)非常相似。準(zhǔn)確一點(diǎn)來說,服務(wù)是可以在后臺長期運(yùn)行的沒有界面的組件。服務(wù)不能自己運(yùn)行,需要通過Contex.startService()或Contex.bindService()啟動(dòng)服務(wù),兩種方式主要區(qū)別就是使用startService()啟動(dòng)的服務(wù)與調(diào)用者沒有關(guān)系,就算調(diào)用者關(guān)閉了,服務(wù)還在后臺一直運(yùn)行,想要停止服務(wù)必須使用Contex.stopService();使用bindService()啟動(dòng)的服務(wù)與調(diào)用者綁定,調(diào)用者一旦關(guān)閉,服務(wù)也就終止,而且通過綁定方式啟動(dòng)服務(wù)時(shí),調(diào)用者可以執(zhí)行服務(wù)中的一些方法。通常情況下可以利用這兩種方式混合啟動(dòng)服務(wù),達(dá)到調(diào)用服務(wù)中的方法,而調(diào)用者關(guān)閉時(shí)服務(wù)又不會(huì)立刻終止的效果。2.2Android開發(fā)環(huán)境的搭建進(jìn)行Android應(yīng)用開發(fā)之前,我們首先要搭建一個(gè)Android應(yīng)用開發(fā)環(huán)境。下面介紹一下如何搭建Android應(yīng)用開發(fā)環(huán)境。Android由多個(gè)開發(fā)包組成的,其中最主要的開發(fā)包如下:JDK(Java語言的軟件開發(fā)工具包):可以到網(wǎng)址/technetwork/java/javase/downloads/index.html下載對應(yīng)系統(tǒng)的JDKAndroidSDK(Android軟件開發(fā)工具包):可以到網(wǎng)址/sdk/index.html#download下載,直接下載ADT即可得到一個(gè)包含有AndroidSDK和Eclipse的開發(fā)工具。Eclipse開發(fā)環(huán)境需要JRE的支持,所以必須先安裝JDK,雙擊我們下載到的JDK安裝包開始安裝,選擇好安裝路徑,按照提示操作即可完成JDK及JRE的安裝。JDK安裝完成后需要配置環(huán)境變量,右鍵點(diǎn)擊我的電腦,選擇屬性,選擇左邊的高級系統(tǒng)設(shè)置,再在彈出的對話框中點(diǎn)擊環(huán)境變量,在用戶變量中新建一個(gè)變量,變量名為PATH,變量值中填上JDK和JRE的安裝目錄下bin文件夾的路徑,中間以“;”隔開。不同系統(tǒng)設(shè)置可能有些許不同,但大體上是一致的。具體過程如以下組圖所示:圖2系統(tǒng)變量設(shè)置圖3系統(tǒng)變量設(shè)置圖4系統(tǒng)變量設(shè)置圖5系統(tǒng)變量設(shè)置配置好環(huán)境變量后需要測試看JDK是否正確安裝,按win+R鍵打開運(yùn)行窗口,在對話框中輸入CMD,在彈出的命令提示符窗口中輸入java按下回車鍵,看是否能打印出信息,再輸javac按下回車看是否能打印出信息,能得到如下圖所示的信息說明JDK與JRE都已正確安裝了。圖6驗(yàn)證JDK是否正確安裝圖7驗(yàn)證JDK是否正確安裝安裝完JDK之后,直接解壓下載到的ADT工具包到你想安裝的路徑下即可得到Eclipse和AndroidSDK以及一個(gè)SDKManager應(yīng)用程序。解壓完成后同樣需要配置環(huán)境變量,雙擊用戶變量中的PATH變量,將SDK中的tools和platform-tools路徑添加到變量值中。然后打開CMD,輸入android–h按下回車鍵,若能打印出幫助信息則說明SDK已經(jīng)正確配置,可以使用了。雙擊打開SDKManager.exe或者打開CMD,輸入命令android打開SDK管理器,在這里下載安裝好開發(fā)時(shí)需要用到的Android系統(tǒng)版本以及工具。圖8SDK管理器安裝好需要的Android系統(tǒng)版本文件后,在CMD中輸入命令androidavd打開AVD管理器,配置Android模擬器,點(diǎn)擊New新建一個(gè)模擬器,選擇好系統(tǒng)版本、屏幕大小、CPU、RAM大小以及SDCard大小后點(diǎn)擊OK即可,屏幕、RAM以及SDCard大小建議不要設(shè)置太大,以免造成模擬器運(yùn)行卡頓。圖9AVD管理器2.3Android音樂播放器工程結(jié)構(gòu)Android工程基本結(jié)構(gòu)目錄包括:src(源代碼)、gen(Android系統(tǒng)自動(dòng)生成的常量)、Res(資源文件):主要存放程序界面的布局配置(.xml)文件和圖片資源。AndroidMainfes.xml是四大組件的驅(qū)動(dòng)配置文件,有它的存在,Android程序的四大組件才可以正常的跳轉(zhuǎn)。Android資源的類型和布局如下圖:圖10Android資源類型和布局下面組圖為音樂播放器代碼結(jié)構(gòu)和各界面的配置文件,圖像資源等,圖11為一個(gè)Android工程所必須的結(jié)構(gòu),圖12為該播放器的類文件,圖13為播放器所用到的字符串,字體大小,字的顏色等配置文件,圖14為該播放器的各種界面的布局配置文件,圖15為該播放器的圖片資源。圖11圖12圖13圖14圖153.系統(tǒng)需求分析本項(xiàng)目目的是開發(fā)一個(gè)可以播放MP3格式音樂文件的播放器,并且能夠控制播放、暫停、上一首、下一首、隨機(jī)播放、列表循環(huán)、單曲循環(huán)等播放模式設(shè)置,具有來電自動(dòng)暫停,掛斷電話自動(dòng)繼續(xù)播放功能,具有歌曲列表功能,具有較好的視覺外觀,界面簡明,操作簡單。根據(jù)項(xiàng)目目標(biāo),我們可以獲得系統(tǒng)的基本需求。下面將介紹系統(tǒng)需求。3.1構(gòu)成模塊本項(xiàng)目構(gòu)成模塊如右圖所示。音樂播放器歌曲列表播放控制對音樂播放器歌曲列表播放控制(1)歌曲列表模塊此模塊將自動(dòng)掃描擴(kuò)展卡中MP3格式的文件并顯示出來,用戶點(diǎn)擊某一歌曲后將會(huì)跳轉(zhuǎn)到播放界。(2)播放控制模塊此模塊功能是控制音樂的播放。具體功能如下。eq\o\ac(○,1)播放用戶點(diǎn)擊播放按鈕時(shí),播放器將播放選中歌曲。圖16模塊結(jié)構(gòu)eq\o\ac(○,2)暫停播放器正在播放時(shí),用戶點(diǎn)擊暫停按鈕,將暫停播放。eq\o\ac(○,3)上一首/下一首用戶點(diǎn)擊上一首或下一首按鈕時(shí),播放器將自動(dòng)播放上一首或下一首歌曲。eq\o\ac(○,4)播放模式播放器默認(rèn)播放模式為順序播放,另有三個(gè)按鈕,分別為隨機(jī)播放、列表循環(huán)、單曲循環(huán),用戶按下相應(yīng)按鈕,播放器播放模式將切換到相應(yīng)的播放模式。3.2系統(tǒng)流程音樂播放器系統(tǒng)流程圖如下圖所示。圖17系統(tǒng)流程圖3.3系統(tǒng)結(jié)構(gòu)音樂播放器系統(tǒng)的完整功能結(jié)構(gòu)如下圖所示。圖18功能結(jié)構(gòu)圖3.4系統(tǒng)需求3.4.1系統(tǒng)界面需求播放器界面要求布局合理,有較好的視覺外觀,界面簡明,操作簡單,為減少開發(fā)工作量,圖片素材均為網(wǎng)上下載到的素材。3.4.2系統(tǒng)性能需求由于Android手機(jī)系統(tǒng)要求的無響應(yīng)時(shí)間為5秒,故有如下性能要求:當(dāng)歌曲列表與播放界面相互跳轉(zhuǎn)時(shí),程序響應(yīng)時(shí)間最長不能超過5秒。當(dāng)要求歌曲播放時(shí),程序響應(yīng)時(shí)間最長不能超過5秒。當(dāng)要求歌曲暫停時(shí),程序響應(yīng)時(shí)間最長不能超過5秒。當(dāng)要求歌曲播放上一首、下一首歌曲時(shí),程序響應(yīng)時(shí)間最長不能超過5秒。3.4.3運(yùn)行環(huán)境需求運(yùn)行系統(tǒng):Android2.1~Android4.3版本開發(fā)環(huán)境:Eclipse4.2.1ADT22.3.04.詳細(xì)設(shè)計(jì)及功能實(shí)現(xiàn)本音樂播放器可用2個(gè)Activity和1個(gè)Service來實(shí)現(xiàn),通過Activity來顯示歌曲列表和播放界面,使用Service在后臺播放音樂,通過一個(gè)Application類來存放全局變量,用于Activity間以及Activity和Service之間數(shù)據(jù)的傳遞。4.1播放器界面的設(shè)計(jì)4.1.1歌曲列表界面設(shè)計(jì)程序啟動(dòng)時(shí)首先進(jìn)入歌曲列表界面,該界面通過一個(gè)RelativeLayout布局來實(shí)現(xiàn),上方使用一個(gè)Textview來顯示標(biāo)題“歌曲列表”,下方是一個(gè)Listview控件,用于顯示從SD卡中掃描得到的歌曲列表。效果如下圖,具體代碼見附件musiclist.xml文件。圖19歌曲列表界面4.1.2播放界面設(shè)計(jì)在歌曲列表中點(diǎn)擊某一首歌曲之后程序則跳轉(zhuǎn)到播放界面中,該界面需要有各種按鈕可以控制音樂播放,播放模式的設(shè)置,以及顯示歌名,播放進(jìn)度等。界面由幾個(gè)LinearLayout布局的嵌套來完成。效果如下圖,具體代碼見附件playui.xml文件。圖20播放界面4.2各模塊詳細(xì)設(shè)計(jì)4.2.1歌曲列表功能進(jìn)入歌曲列表時(shí)需要自動(dòng)掃描SD卡中的MP3文件,掃描到文件則顯示歌曲列表,掃描不到文件則彈出提示,并自動(dòng)退出程序。掃描歌曲代碼如下。privatevoidMusicList(){ Filehome=newFile(myApp.getPath());//從Application中獲取SD卡路徑并創(chuàng)建一個(gè)文件夾 if(home.listFiles(newMusicFilter()).length>0){//如果文件夾下的歌曲數(shù)目大于0,則執(zhí)行下面的方法 for(Filefile:home.listFiles(newMusicFilter())){//遍歷home文件夾下面的歌曲 myMusicList.add(file.getName());//把每一次遍歷到的歌曲名字添加到myMusicList表中 } ArrayAdapter<String>musicList=newArrayAdapter<String>( musicListActivity.this,R.layout.liststyle,myMusicList); //調(diào)用數(shù)組適配器,myMusicList表單中的信息顯示到list視圖中 setListAdapter(musicList);//添加適配器 }elseif(home.listFiles(newMusicFilter()).length==0){ Toast.makeText(musicListActivity.this,"找不到歌曲,請?jiān)赟D卡中添加音樂文件后重啟程序",0) .show();//找不到歌曲時(shí)彈出一個(gè)Toast提示 handler.postDelayed(runable,2000);//調(diào)用進(jìn)程延遲兩秒結(jié)束程序 } }點(diǎn)擊列表中歌曲時(shí)程序自動(dòng)跳轉(zhuǎn)到播放界面,可在播放界面中控制播放音樂,代碼如下。//監(jiān)聽ListItem點(diǎn)擊事件protectedvoidonListItemClick(android.widget.ListViewl, android.view.Viewv,intposition,longid){ super.onListItemClick(l,v,position,id); if(myApp.getNum()!=position){ myApp.setNum(position); replay=1; }else{ replay=0; } Intentintent=newIntent(musicListActivity.this,PlayActivity.class); intent.putExtra("replay",replay); startActivity(intent);//跳轉(zhuǎn)到播放界面 };4.2.2播放/暫停模塊播放界面中,播放與暫停為同一個(gè)按鈕,一個(gè)按鈕實(shí)現(xiàn)兩個(gè)功能,當(dāng)歌曲正在播放時(shí),按下按鈕為暫停播放功能;當(dāng)歌曲不在播放時(shí),按下按鈕則為播放功能。兩個(gè)功能切換的同時(shí)需要切換到相應(yīng)的按鈕圖片素材。代碼如下。privateclassplayListenerimplementsOnClickListener{ publicvoidonClick(Viewv){ if(myservice.isplay()){ if(replay==1){ myservice.play(); playButton.setImageResource(R.drawable.pause); replay=0; handler.post(runnable); }else{ playButton.setImageResource(R.drawable.play); myservice.pause(); replay=0; } }else{ playButton.setImageResource(R.drawable.pause); if(replay==1){ myservice.play(); replay=0; handler.post(runnable); }else{ myservice.start(); } } }}播放與暫停的功能實(shí)現(xiàn)則在Service中完成,代碼如下。//播放當(dāng)前音樂publicvoidplay(){ try{ myMediaPlayer.reset(); myMediaPlayer.setDataSource(myApp.getSongPath()); myMediaPlayer.prepare(); myMediaPlayer.start(); }catch(Exceptione){ e.printStackTrace(); } myApp.setIsPlay(1); //監(jiān)聽歌曲是否播完,播完自動(dòng)播放下一首 myMediaPlayer.setOnCompletionListener(newOnCompletionListener(){ publicvoidonCompletion(MediaPlayerarg0){ moveNext(); } });}//繼續(xù)播放publicvoidstart(){ myMediaPlayer.start(); myApp.setIsPlay(1);}//暫停播放publicvoidpause(){ myMediaPlayer.pause(); myApp.setIsPlay(0);}4.2.3播放進(jìn)度模塊播放界面中播放進(jìn)度是通過一個(gè)SeekBar控件來完成的,通過定義一個(gè)進(jìn)程來更新界面,監(jiān)聽播放進(jìn)度的改變,實(shí)現(xiàn)更新進(jìn)度條以及播放時(shí)間。再定義一個(gè)方法監(jiān)聽SeekBar改變,用戶點(diǎn)擊進(jìn)度條時(shí)音樂將跳到該位置進(jìn)行播放。具體代碼如下。Handlerhandler=newHandler();//定義一個(gè)handler,主要是用于更新進(jìn)度條Runnablerunnable=newRunnable(){ //重寫run方法 publicvoidrun(){ seekbar.setMax(myservice.getDuration());//獲取歌曲時(shí)長設(shè)置進(jìn)度條最大值 seekbar.setProgress(myservice.getCurrentPosition());//獲取音樂播放的時(shí)間來設(shè)定進(jìn)度條的位置 currentTime.setText(formatTime(myservice.getCurrentPosition()));//顯示當(dāng)前播放時(shí)間 maxTime.setText(formatTime(myservice.getDuration()));//顯示歌曲時(shí)長 filename.setText(myApp.getFileName());//顯示歌名 handler.postDelayed(runnable,1000);//每隔1秒鐘更新一次 }};//格式化時(shí)間,將其變成00:00的形式publicStringformatTime(inttime){ intsecondSum=time/1000;//時(shí)間轉(zhuǎn)化成秒 intminute=secondSum/60;//得到分鐘數(shù) intsecond=secondSum%60;//得到秒數(shù) Stringresult=""; if(minute<10) result="0"; result=result+minute+":"; if(second<10) result=result+"0"; result=result+second; returnresult;}privatevoidSeekBarChange(){ //監(jiān)聽SeekBar改變 seekbar.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener(){ publicvoidonStopTrackingTouch(SeekBarseekBar){ } publicvoidonStartTrackingTouch(SeekBarseekBar){ } publicvoidonProgressChanged(SeekBarseekBar,intprogress, booleanfromUser){ if(fromUser==true){//當(dāng)進(jìn)度條焦點(diǎn)發(fā)生改變時(shí),fromUser就為true myservice.seekTo(progress);//把當(dāng)前歌曲的位置跳轉(zhuǎn)到進(jìn)度條的位置 } } });}//使歌曲跳到指定位置播放publicvoidseekTo(intmsec){ myMediaPlayer.seekTo(msec);}//返回當(dāng)前播放時(shí)間publicintgetCurrentPosition(){ returnmyMediaPlayer.getCurrentPosition();}//返回歌曲時(shí)長publicintgetDuration(){ returnmyMediaPlayer.getDuration();}4.2.4播放模式模塊默認(rèn)播放模式為順序播放,播放最后一首歌曲時(shí),若歌曲播完或者用戶點(diǎn)擊下一首,則彈出提示,并停止音樂;播放第一首歌曲時(shí),若用戶點(diǎn)擊上一首,則彈出提示,并停止音樂。用戶按下界面下方三個(gè)播放模式控制按鈕(分別為隨機(jī)播放、列表循環(huán)、單曲循環(huán))時(shí),程序自動(dòng)切換到相應(yīng)的播放模式,代碼如下,相應(yīng)的播放功能在Service中的上一首及下一首模塊中實(shí)現(xiàn)。privateclasslistListenerimplementsOnTouchListener{ publicbooleanonTouch(Viewv,MotionEventevent){ if(event.getAction()==MotionEvent.ACTION_DOWN){ listButton.setImageResource(R.drawable.listpress); }elseif(event.getAction()==MotionEvent.ACTION_UP){ //若當(dāng)前為列表循環(huán)則切換到默認(rèn)模式 if(playMode.equals("listloop")){ playMode="normal"; myApp.setPlayMode(playMode); listButton.setImageResource(R.drawable.list); } //否則切換到列表循環(huán)模式,同時(shí)其他兩個(gè)按鈕切換到未按下的狀態(tài) else{ playMode="listloop"; myApp.setPlayMode(playMode);//設(shè)置播放模式為列表循環(huán) listButton.setImageResource(R.drawable.listpress); shuffleButton.setImageResource(R.drawable.shuffle); repeatButton.setImageResource(R.drawable.repeat); } } returnfalse; }}privateclassshuffleListenerimplementsOnTouchListener{ publicbooleanonTouch(Viewv,MotionEventevent){ if(event.getAction()==MotionEvent.ACTION_DOWN){ shuffleButton.setImageResource(R.drawable.shufflepress); }elseif(event.getAction()==MotionEvent.ACTION_UP){ //若當(dāng)前為隨機(jī)播放則切換到默認(rèn)模式 if(playMode.equals("shuffle")){ playMode="normal"; myApp.setPlayMode(playMode); shuffleButton.setImageResource(R.drawable.shuffle); } //否則切換到隨機(jī)播放模式,同時(shí)其他兩個(gè)按鈕切換到未按下的狀態(tài) else{ playMode="shuffle"; myApp.setPlayMode(playMode); shuffleButton.setImageResource(R.drawable.shufflepress); listButton.setImageResource(R.drawable.list); repeatButton.setImageResource(R.drawable.repeat); } } returnfalse; }}privateclassrepeatListenerimplementsOnTouchListener{ publicbooleanonTouch(Viewv,MotionEventevent){ if(event.getAction()==MotionEvent.ACTION_DOWN){ repeatButton.setImageResource(R.drawable.repeatpress); }elseif(event.getAction()==MotionEvent.ACTION_UP){ //若當(dāng)前為單曲循環(huán)則切換到默認(rèn)模式 if(playMode.equals("repeat")){ playMode="normal"; myApp.setPlayMode(playMode); repeatButton.setImageResource(R.drawable.repeat); } //否則切換到單曲循環(huán)模式,同時(shí)其他兩個(gè)按鈕切換到未按下的狀態(tài) else{ playMode="repeat"; myApp.setPlayMode(playMode); repeatButton.setImageResource(R.drawable.repeatpress); shuffleButton.setImageResource(R.drawable.shuffle); listButton.setImageResource(R.drawable.list); } } returnfalse; }}4.2.5上一首/下一首模塊用戶按下上一首或者下一首按鈕時(shí),根據(jù)當(dāng)前播放模式切換到上一首或者下一首,按鈕的點(diǎn)擊事件在播放界面中實(shí)現(xiàn),具體播放功能在Service中實(shí)現(xiàn)。代碼如下。privateclasspreListenerimplementsOnClickListener{ publicvoidonClick(Viewv){ myservice.movePre();//調(diào)用服務(wù)中的方法,播放上一首 replay=0;//設(shè)置標(biāo)識符為不需要重新播放 playButton.setImageResource(R.drawable.pause);//播放按鈕切換為暫停功能 handler.post(runnable);//啟動(dòng)進(jìn)程更新進(jìn)度條及時(shí)間 if(myApp.getIsPlay()==0){//需要停止播放 replay=1;//設(shè)置標(biāo)識符為需要重新播放 playButton.setImageResource(R.drawable.play);//播放按鈕切換到播放功能 } }}privateclassnextListenerimplementsOnClickListener{ publicvoidonClick(Viewv){ myservice.moveNext();//調(diào)用服務(wù)中的方法,播放下一首 replay=0;//設(shè)置標(biāo)識符為不需要重新播放 playButton.setImageResource(R.drawable.pause);//播放按鈕切換為暫停功能 handler.post(runnable);//啟動(dòng)進(jìn)程更新進(jìn)度條及時(shí)間 if(myApp.getIsPlay()==0){//需要停止播放 replay=1;//設(shè)置標(biāo)識符為需要重新播放 playButton.setImageResource(R.drawable.play);//播放按鈕切換到播放功能 } }}//上一首publicvoidmovePre(){ num=myApp.getNum(); if(myApp.getPlayMode().equals("normal")){ if(num-1>=0){ myApp.setNum(num-1); play(); myApp.setIsPlay(1); }else{ myMediaPlayer.pause(); Toast.makeText(getApplicationContext(),"已經(jīng)是第一首,請重新選擇歌曲",0).show(); myApp.setIsPlay(0); } }elseif(myApp.getPlayMode().equals("listloop")){ if(num-1>=0){ myApp.setNum(num-1); play(); }else{ myApp.setNum(myMusicList.size()-1); play(); myApp.setIsPlay(1); } }elseif(myApp.getPlayMode().equals("shuffle")){ num=random.nextInt(myMusicList.size()); if(myApp.getListSize()>=2){ while(num==myApp.getNum()){ num=random.nextInt(myMusicList.size()); } } myApp.setNum(num); play(); myApp.setIsPlay(1); }elseif(myApp.getPlayMode().equals("repeat")){ play(); myApp.setIsPlay(1); }}//下一首publicvoidmoveNext(){ num=myApp.getNum(); if(myApp.getPlayMode().equals("normal")){ if(num+1<myMusicList.size()){ myApp.setNum(num+1); play(); myApp.setIsPlay(1); }else{ myMediaPlayer.pause(); Toast.makeText(getApplicationContext(),"沒有歌曲了,請重新選擇歌曲",0).show(); myApp.setIsPlay(0); } }elseif(myApp.getPlayMode().equals("listloop")){ If(num+1<myMusicList.size()){ myApp.setNum(num+1); play(); myApp.setIsPlay(1); }else{ myApp.setNum(0); play(); myApp.setIsPlay(1); } }elseif(myApp.getPlayMode().equals("shuffle")){ num=random.nextInt(myMusicList.size()); if(myApp.getListSize()>=2){ while(num==myApp.getNum()){ num=random.nextInt(myMusicList.size()); } } myApp.setNum(num); play(); myApp.setIsPlay(1); }elseif(myApp.getPlayMode().equals("repeat")){ play(); myApp.setIsPlay(1); }}4.2.6來電暫停功能模塊Android開發(fā)中可以利用TelephonyManager這個(gè)API來監(jiān)聽電話狀態(tài)的改變,電話狀態(tài)一旦改變就會(huì)調(diào)用一個(gè)回調(diào)方法,通過重寫該方法,可以實(shí)現(xiàn)來電暫停播放,掛電話自動(dòng)播放的功能。具體代碼如下。TelephonyManagertelephonyManager=(TelephonyManager)getSystemService(TELEPHONY_SERVICE);//監(jiān)聽電話狀態(tài)telephonyManager.listen(newMyPhoneListener(),PhoneStateListener.LISTEN_CALL_STATE);privatefinalclassMyPhoneListenerextendsPhoneStateListener{//電話狀態(tài)改變時(shí)調(diào)用,來電時(shí)暫停播放,掛斷電話時(shí)繼續(xù)播放publicvoidonCallStateChanged(intstate,StringincomingNumber){ switch(state){ caseTelephonyManager.CALL_STATE_RINGING://來電 if(isplay()){ position=getCurrentPosition(); pause(); } break; caseTelephonyManager.CALL_STATE_IDLE://掛斷電話 if(position>0){
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年河南省安全員考試題庫及答案
- 水處理劑運(yùn)輸協(xié)議
- 2025年度合伙項(xiàng)目退出合同:投資回收與風(fēng)險(xiǎn)承擔(dān)
- 教育培訓(xùn)機(jī)構(gòu)外墻裝修樣本
- 2025年度產(chǎn)品安全召回賠償協(xié)議范本
- 2025年度個(gè)人綠色建筑投資管理協(xié)議
- 2025年度解除終止勞動(dòng)合同后員工離職手續(xù)辦理指南
- 2025年度債權(quán)轉(zhuǎn)讓合同-金融資產(chǎn)重組
- 2025年度員工借調(diào)及數(shù)字化轉(zhuǎn)型合作協(xié)議
- 2025年度廣告?zhèn)髅絼趧?wù)派遣安全服務(wù)協(xié)議
- - 《中國課件》揭示西安古都的千年歷史與文化
- 2025年度空調(diào)安裝驗(yàn)收及保修服務(wù)合同
- 急救護(hù)理學(xué)第十章災(zāi)難救護(hù)講解
- 《Maya三維模型制作項(xiàng)目式教程(微課版)》全套教學(xué)課件
- 2024年北京電子科技職業(yè)學(xué)院高職單招語文歷年參考題庫含答案解析
- 2024版消防設(shè)計(jì)質(zhì)量問題案例分析手冊建筑機(jī)電專業(yè)
- 《業(yè)財(cái)一體化實(shí)訓(xùn)教程-金蝶云星空V7.5》
- 工業(yè)機(jī)器人工作站系統(tǒng)組建課件 5.1康耐視is2000工業(yè)相機(jī)視覺識別操作
- 人教版二年級數(shù)學(xué)下冊第一單元綜合測評卷(含答案)
- 社區(qū)意識形態(tài)工作2025年度工作計(jì)劃
- 2025年山東省濟(jì)南廣播電視臺招聘30人歷年管理單位筆試遴選500模擬題附帶答案詳解
評論
0/150
提交評論