Android多功能音樂播放器設(shè)計(jì)說明_第1頁
Android多功能音樂播放器設(shè)計(jì)說明_第2頁
Android多功能音樂播放器設(shè)計(jì)說明_第3頁
Android多功能音樂播放器設(shè)計(jì)說明_第4頁
Android多功能音樂播放器設(shè)計(jì)說明_第5頁
已閱讀5頁,還剩31頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

.31/36.

畢業(yè)論文設(shè)計(jì)(論文)題目:Android多功能音樂播放器設(shè)計(jì)學(xué)位論文原創(chuàng)性聲明本人重聲明:所呈交的論文是本人在導(dǎo)師的指導(dǎo)下獨(dú)立進(jìn)行研究所取得的研究成果。除了文中特別加以標(biāo)注引用的容外,本論文不包含任何其他個(gè)人或集體已經(jīng)發(fā)表或撰寫的成果作品。對本文的研究做出重要貢獻(xiàn)的個(gè)人和集體,均已在文中以明確方式標(biāo)明。本人完全意識到本聲明的法律后果由本人承擔(dān)。作者簽名: 日期:年月日學(xué)位論文使用授權(quán)書本學(xué)位論文作者完全了解學(xué)校有關(guān)保留、使用學(xué)位論文的規(guī)定,同意學(xué)校保留并向國家有關(guān)部門或機(jī)構(gòu)送交論文的復(fù)印件和電子版,允許論文被查閱和借閱。本人授權(quán)大學(xué)可以將本學(xué)位論文的全部或部分容編入有關(guān)數(shù)據(jù)庫進(jìn)行檢索,可以采用影印、縮印或掃描等復(fù)制手段保存和匯編本學(xué)位論文。涉密論文按學(xué)校規(guī)定處理。作者簽名: 日期:年月日導(dǎo)師簽名:日期:年月日目錄Android多功能音樂播放器設(shè)計(jì)III摘要IIIAbstract IV1緒論11.1課題開發(fā)的背景與意義11.2研究現(xiàn)狀12Android介紹22.1什么是android?22.2Android基本框架(AndroidArchitecture)22.3系統(tǒng)的四大組件42.4Android特性53系統(tǒng)需求分析63.1功能需求63.1.1播放器的基本控制需求63.1.2播放清單列表管理需求73.1.3播放友好性需求93.1.4功能需求(時(shí)序圖)分析103.2系統(tǒng)結(jié)構(gòu)圖和流程圖103.3系統(tǒng)界面需求123.4系統(tǒng)性能需求133.4.1如何避免ANR 143.4.2增強(qiáng)響應(yīng)性143.5運(yùn)行環(huán)境需求154Android音樂播放器系統(tǒng)設(shè)計(jì)164.1音樂播放器界面功能實(shí)現(xiàn)164.2本地音樂與網(wǎng)絡(luò)音樂播放功能實(shí)現(xiàn)204.3數(shù)據(jù)存儲方式214.3.1SharedPreferences 214.3.2File存儲方式224.3.3SQLiteDatabase數(shù)據(jù)庫225系統(tǒng)運(yùn)行與測試235.1調(diào)試工具介紹235.1.1通過Logcat來調(diào)試程序:235.1.2通過Traceview來調(diào)試程序:235.1.3通過adb來調(diào)試程序:235.2調(diào)試中出現(xiàn)的問題與解決方法245.3編譯運(yùn)行程序255.3.1編譯程序255.3.2運(yùn)行程序255.4系統(tǒng)存在的不足27結(jié)論28參考文獻(xiàn)29致30Android多功能音樂播放器設(shè)計(jì)摘要隨著Android平臺的興起,移動(dòng)音樂已成為很多手機(jī)用戶休閑時(shí)的主要愛好之一,因此一款免費(fèi)的,界面簡潔,性能優(yōu)異的音樂播放器將會得到廣大音樂愛好者的支持。本文首先介紹了Android系統(tǒng)的架構(gòu)和特點(diǎn),然后在分析需求的基礎(chǔ)上,詳細(xì)論述利用Eclipse開發(fā)平臺、AndroidSDK、AndroidADT設(shè)計(jì)出音樂播放器的具體方法。該播放器支持播放本地與網(wǎng)絡(luò)音樂、搜索、下載,并且能自動(dòng)匹配歌詞和專輯圖片,具有一定實(shí)用性。關(guān)鍵詞:Android;音樂播放器;下載AndroidMediaPlayerAbstractWiththeriseoftheAndroidplatform,mobilemusichasbecomeoneofthemainhobbyofleisuretimealotofmobilephoneusers,thereforeafree,simpleinterface,excellentmusicplayerwillgetthesupportofthemajorityofmusiclovers.ThispaperfirstintroducesthearchitectureandfeaturesoftheAndroidsystem,andthenonthebasisoftheanalysisofdemandisdiscussedindetailusingtheEclipsedevelopmentplatform,theAndroidSDK,AndroidADTtodesignaspecificmethodofthemusicplayer.Theplayersupportsplaybackoflocalandonlinemusicsearch,downloadandcanautomaticallymatchthelyricsandalbumart,withacertainpracticality.Keywords:Android;MediaPlayer;Download1緒論1.1課題開發(fā)的背景與意義近年來,移動(dòng)通信和互聯(lián)網(wǎng)成為當(dāng)今世界發(fā)展最快、市場潛力最大、前景最誘人的兩大業(yè)務(wù),它們的增長速度是任何預(yù)測家未曾預(yù)料到的。迄今,全球移動(dòng)用戶已超過15億,互聯(lián)網(wǎng)用戶也已逾7億。中國移動(dòng)通信用戶總數(shù)超過3.6億,互聯(lián)網(wǎng)用戶總數(shù)則超過1億。目前,移動(dòng)互聯(lián)網(wǎng)正逐漸滲透到人們生活、工作的各個(gè)領(lǐng)域,短信、下載、移動(dòng)音樂、手機(jī)游戲、視頻應(yīng)用、手機(jī)支付、位置服務(wù)等豐富多彩的移動(dòng)互聯(lián)網(wǎng)應(yīng)用迅猛發(fā)展,正在深刻改變信息時(shí)代的社會生活。移動(dòng)音樂在日常生活中有著非常重要的作用,用手機(jī)收聽音樂,已經(jīng)是很多手機(jī)用戶閑暇時(shí)的主要愛好之一,擁有一款功能強(qiáng)大的手機(jī)音樂播放器也是很多愛好聽音樂的手機(jī)用戶的追求,因此一款能夠提供極佳的音質(zhì)音效、支持隨時(shí)隨地播放、搜索、下載歌曲,并且能自動(dòng)匹配歌詞和專輯圖片的音樂播放器將會得到廣大音樂愛好者的支持。1.2研究現(xiàn)狀隨著移動(dòng)互聯(lián)網(wǎng)的發(fā)展,近年來智能手機(jī)的發(fā)展也更加迅速,市場上出現(xiàn)了多種手機(jī)操作系統(tǒng),其中主流的操作系統(tǒng)有Symbian、WindowsPhone、Android、ios、黑莓等,其中具有開放源代碼優(yōu)勢的Android操作系統(tǒng)有著巨大的發(fā)展前景。由于谷歌Android系統(tǒng)開放,因此我們完全能夠在手機(jī)上擁有一款個(gè)性化的音樂播放器。Google的Android系統(tǒng)是一種以Linux為基礎(chǔ)的開放源碼操作系統(tǒng),主要使用于便攜設(shè)備。Android操作系統(tǒng)最初由AndyRubin開發(fā),最初主要支持手機(jī)。2005年由Google收購注資,并組建開放手機(jī)聯(lián)盟開發(fā)改良,逐漸擴(kuò)展到平板電腦與其他領(lǐng)域上。Android的主要競爭對手是蘋果公司的iOS以與RIM的BlackberryOS。2011年第一季度,Android在全球的市場份額首次超過塞班系統(tǒng),躍居全球第一。2011年11月數(shù)據(jù),Android占據(jù)全球智能手機(jī)操作系統(tǒng)市場52.5%的份額,中國市場占有率為58%?,F(xiàn)如今,就安卓平臺而言,很多播放器一味追求外觀花哨,功能龐大,對用戶的手機(jī)資源造成了很多資源浪費(fèi),比如CPU,存等占用率過高,在用戶需要多任務(wù)操作時(shí),受到了不小的影響,帶來了許多不便,而對于大多數(shù)普通用戶,許多功能用不上,形同虛設(shè)。針對以上各種弊端,開發(fā)一款功能全面,界面簡潔,性能優(yōu)異的音頻播放器軟件一定會受到用戶歡迎。2Android介紹2.1什么是android?Android一詞的本義指“機(jī)器人”,同時(shí)也是Google于2007年11月5日宣布的基于Linux平臺的開源手機(jī)操作系統(tǒng)的名稱,該平臺由操作系統(tǒng)、中間件、用戶界面和應(yīng)用軟件組成,號稱是首個(gè)為移動(dòng)終端打造的真正開放和完整的移動(dòng)軟件。Android是基于Linux核的軟件平臺和操作系統(tǒng),早期由Google開發(fā)(在華注冊商標(biāo)名為“安致”),后由開放手機(jī)聯(lián)盟(OpenHandsetAlliance)開發(fā)。它采用了軟件堆層(softwarestack,又名以軟件疊層)的架構(gòu),主要分為三部分。低層以Linux核工作為基礎(chǔ),只提供基本功能;其他的應(yīng)用軟件則由各公司自行開發(fā),以Java作為編寫程序的一部分。2.2Android基本框架(AndroidArchitecture)圖2.1AndroidArchitecture1.ApplicationsApplicationAndroid會同一個(gè)核心應(yīng)用程序包一起發(fā)布,該應(yīng)用程序包包括email客戶端,SMS短消息程序,日歷,地圖,瀏覽器,聯(lián)系人管理程序等。所有的應(yīng)用程序都是用JAVA編寫的。2.ApplicationFrameWork開發(fā)者完全可以訪問核心應(yīng)用程序所使用的API框架。該應(yīng)用程序架構(gòu)用來簡化組件軟件的重用;任何一個(gè)應(yīng)用程序都可以發(fā)布它的功能塊并且任何其它的應(yīng)用程序都可以使用其所發(fā)布的功能塊(不過得遵循框架的安全性限制)。該應(yīng)用程序重用機(jī)制使得組建可以被用戶替換。所有的應(yīng)用程序都由一系列的服務(wù)和系統(tǒng)組成,包括:·可擴(kuò)展的視圖(Views)可以用來建應(yīng)用程序,包括列表(lists),網(wǎng)格(grids),文本框(textboxes),按鈕(buttons),甚至包括一個(gè)可嵌入的web瀏覽器·容管理器(ContentProviders)使得應(yīng)用程序可以訪問另一個(gè)應(yīng)用程序的數(shù)據(jù)(如聯(lián)系人數(shù)據(jù)庫),或者共享它們自己的數(shù)據(jù)?!べY源管理器(ResourceManager)提供非代碼資源的訪問,如本地字符串,圖形,和分層文件(layoutfiles)?!ねㄖ芾砥鳎∟otificationManager)使得應(yīng)用程序可以在狀態(tài)欄中顯示客戶通知信息。·活動(dòng)類管理器(ActivityManager)用來管理應(yīng)用程序生命周期并提供常用的導(dǎo)航回退功能。3.Libraries庫Android包括一個(gè)被Android系統(tǒng)中各種不同組件所使用的C/C++庫集。該庫通過Android應(yīng)用程序框架為開發(fā)者提供服務(wù)。以下是一些主要的核心庫:系統(tǒng)C庫一個(gè)從BSD繼承來的標(biāo)準(zhǔn)C系統(tǒng)函數(shù)庫(libc),專門為基于embeddedlinux的設(shè)備定制。媒體庫-基于PacketVideoOpenCORE;該庫支持錄放,并且可以錄制許多流行的音頻視頻格式,還有靜態(tài)映像文件包括MPEG4,H.264,MP3,AAC,AMR,JPG,PNG。SurfaceManager-對顯示子系統(tǒng)的管理,并且為多個(gè)應(yīng)用程序提供2D和3D圖層的無縫融合。LibWebCore-一個(gè)最新的web瀏覽器引擎用來支持Android瀏覽器和一個(gè)可嵌入的web視圖。SGL-一個(gè)置的2D圖形引擎3Dlibraries-基于OpenGLES1.0APIs實(shí)現(xiàn);該庫可以使用硬件3D加速(如果可用)或者使用高度優(yōu)化的3D軟加速。FreeType-位圖(bitmap)和向量(vector)字體顯示。SQLite一個(gè)對于所有應(yīng)用程序可用,功能強(qiáng)勁的輕型關(guān)系型數(shù)據(jù)庫引擎。4.AndroidRuntimeAndroid包括了一個(gè)核心庫,該核心庫提供了JAVA編程語言核心庫的大多數(shù)功能。每一個(gè)Android應(yīng)用程序都在它自己的進(jìn)程中運(yùn)行,都擁有一個(gè)獨(dú)立的Dalvik虛擬機(jī)實(shí)例。Dalvik是針對于同時(shí)高效地運(yùn)行多個(gè)VM來實(shí)現(xiàn)的。Dalvik虛擬機(jī)執(zhí)行.dex的Dalvik可執(zhí)行文件,該格式文件針對最小存使用做了優(yōu)化。該虛擬機(jī)是基于寄存器的,所有的類都經(jīng)由JAVA匯編器編譯,然后通過SDK中的dx工具轉(zhuǎn)化成.dex格式由虛擬機(jī)執(zhí)行。Dalvik虛擬機(jī)依賴于linux的一些功能,比如線程機(jī)制和底層存管理機(jī)制。5.Linux核Android的核心系統(tǒng)服務(wù)依賴于Linux2.6核,如安全性,存管理,進(jìn)程管理,網(wǎng)絡(luò)協(xié)議棧和驅(qū)動(dòng)模型。Linux核也同時(shí)作為硬件和軟件堆棧之間的硬件抽象層。與iPhone相似,Android采用WebKit瀏覽器引擎,具備觸摸屏、高級圖形顯示和上網(wǎng)功能,用戶能夠在手機(jī)上查看電子、搜索網(wǎng)址和觀看視頻節(jié)目等,比iPhone等其他手機(jī)更強(qiáng)調(diào)搜索功能,界面更強(qiáng)大,可以說是一種融入全部Web應(yīng)用的單一平臺。2.3系統(tǒng)的四大組件在Android系統(tǒng)中,為我們提供了四大基本組件,每個(gè)組件是一個(gè)視圖,但是有些是可見的,有些是不可見的視圖,像Activity,ContentProvider是可見的視圖,Service和BroadcastReceiver是不可見的,它們只在系統(tǒng)的后臺運(yùn)行。下面分別介紹四大組件:1.Activity簡介在Android系統(tǒng)中Activity提供可視化的用戶界面,一個(gè)Android應(yīng)用通常由多個(gè)Activity組成。多個(gè)Activity組成了Activity棧(Stack),當(dāng)前活動(dòng)的Activity處于棧頂。Activity有自己的生命周期,由Android系統(tǒng)來控制。2.Service簡介顧名思義Service就是運(yùn)行在后臺的一種服務(wù)程序,一般很少和用戶交互,因此沒有可視化界面定義一個(gè)Service類比較簡單,只要繼承Service類,實(shí)現(xiàn)其生命周期中的方法就可以了。一個(gè)定義好的Service必須在AndroidManifest.xml配置文件注冊,通過<service>元素聲明才能使用.Service有自己的生命周期,我們可以調(diào)用startService()啟動(dòng)一個(gè)Service或者bindService()方法來綁定一個(gè)存在的Service3.BroadcastReceiver簡介BroadcastReceiver顧名思義廣播接收器,它和事件處理機(jī)制類似,只不過事件處理機(jī)制是程序組件級別的(例如,某個(gè)按鈕的單擊事件),而廣播事件處理機(jī)制是系統(tǒng)級別的。到目前為止我們可以使用Intent來啟動(dòng)一個(gè)程序組件,我們還可以通過使用sendBroadcast()方法來發(fā)起一個(gè)系統(tǒng)級別的事件廣播來傳遞消息。我們可以在你的應(yīng)用程序中實(shí)現(xiàn)BroadcastReceiver來監(jiān)聽和響應(yīng)這些廣播的Intent4.ContentProvider簡介ContentProvider用來保存和檢索數(shù)據(jù),并且使應(yīng)用程序之間相互訪問數(shù)據(jù)成為可能。它是跨應(yīng)用程序共享數(shù)據(jù)的唯一方法。Android為常用的數(shù)據(jù)類型(如:音視頻、圖片和聯(lián)系方式等)提供了大量的ContentProvider。它們被定義在vider包下面。通過這樣定義好的ContentProvider我們可以方便的進(jìn)行數(shù)據(jù)操作。當(dāng)然我們必須擁有適當(dāng)?shù)臋?quán)限。我們也可以自己來定ContentProvider共享我們的數(shù)據(jù),方便用戶的訪問2.4Android特性Android系統(tǒng)有如下的幾大特性:·應(yīng)用程序框架支持組件的重用與替換·Dalvik虛擬機(jī)專門為移動(dòng)設(shè)備做了優(yōu)化·部集成瀏覽器該瀏覽器基于開源的WebKit引擎·優(yōu)化的圖形庫包括2D和3D圖形庫,3D圖形庫基于OpenGLES·SQLite用作結(jié)構(gòu)化的數(shù)據(jù)存儲·多媒體支持包括常見的音頻、視頻和靜態(tài)印象文件格式(如MPEG4,H.264,MP3,AAC,AMR,JPG,PNG,GIF)·GSM(依賴于硬件)·藍(lán)牙Bluetooth,EDGE,3G,andWiFi(依賴于硬件)·照相機(jī),GPS,指南針,和加速度計(jì)(依賴于硬件)·豐富的開發(fā)環(huán)境包括設(shè)備模擬器,調(diào)試工具,存與性能分析圖表,和Eclipse集成開發(fā)環(huán)境插件3系統(tǒng)需求分析3.1功能需求根據(jù)項(xiàng)目的目標(biāo),我們可獲得項(xiàng)目系統(tǒng)的基本需求,以下從不同角度來描述系統(tǒng)的需求,并且使用例圖來描述,系統(tǒng)的功能需求,我們分成四部分來概括,即播放器的基本控制需要,播放列表管理需求,播放器友好性需求和播放器擴(kuò)展卡需求。以下分別描述:播放播放暫停停止上一首/下一首音量控制專輯封面顯示歌詞顯示本地歌曲列表網(wǎng)絡(luò)歌曲列表搜索相關(guān)設(shè)置用戶圖3.1音樂播放器基本控制圖3.1.1播放器的基本控制需求表3.1播放器的基本控制需求表用例名稱:播放參與者:用戶目標(biāo):使得用戶可以播放在播放列表中選中的歌曲前置條件:播放器正在運(yùn)行基本事件流:1.用戶單擊“播放”按鈕2.播放器將播放列表中的當(dāng)前的歌曲用例名稱:暫停參與者:用戶目標(biāo):使得用戶可以暫停正在播放的歌曲前置條件:歌曲正在播放且未停止和暫?;臼录鳎?.用戶單擊“暫?!卑粹o2.播放器將暫停當(dāng)前的歌曲用例名稱:停止參與者:用戶目標(biāo):使得用戶可以停止正在播放的歌曲前置條件:歌曲正在播放或暫?;臼录鳎?.用戶單擊“停止”按鈕2.播放器將停止當(dāng)前播放的歌曲用例名稱:上一首/下一首參與者:用戶目標(biāo):使得用戶可以聽上一首或下一首歌曲前置條件:歌曲正在播放或暫?;臼录鳎?.用戶單擊“上一首或下一首”按鈕2.播放器將播放上一首或下一首歌曲用例名稱:播放清單參與者:用戶目標(biāo):使得用戶可以進(jìn)入播放清單前置條件:程序在運(yùn)行基本事件流:1.用戶單擊“清單”按鈕2.播放器進(jìn)入清單列表3.1.2播放清單列表管理需求當(dāng)用戶選中列表中某一項(xiàng)歌曲,就有的需求:播放播放添加至播放列表刪除用戶圖3.2選中列表中某歌曲時(shí)需求圖表3.2播放器的基本控制需求表用例名稱:播放參與者:用戶目標(biāo):使得程序播放選中的歌曲前置條件:程序運(yùn)行在播放菜單選項(xiàng)中基本事件流:1.用戶單擊“播放”按鈕2.播放器進(jìn)入播放狀態(tài)用例名稱:添加至播放列表參與者:用戶目標(biāo):將歌曲添加到歌曲列表前置條件:程序運(yùn)行在文件瀏覽界面基本事件流:1.用戶單擊“增加”按鈕2.播放器進(jìn)入手機(jī)擴(kuò)展SD卡用例名稱:刪除參與者:用戶目標(biāo):使選中的歌曲被刪除前置條件:程序運(yùn)行在播放菜單選項(xiàng)中基本事件流:1.用戶單擊“刪除”按鈕2.播放器移除選中歌曲3.1.3播放友好性需求用戶用戶播放模式專輯封面單曲循環(huán)循環(huán)播放歌詞顯示隨機(jī)播放圖3.3播放友好需求圖表3.3播放友好需求表用例名稱:播放模式參與者:用戶目標(biāo):使得程序進(jìn)入播放模式設(shè)定狀態(tài)前置條件:程序運(yùn)行在播放器設(shè)定界面中基本事件流:1.用戶單擊“順序、隨機(jī)、單曲”按鈕2.播放器進(jìn)入選中模式播放狀態(tài)用例名稱:歌詞顯示參與者:用戶目標(biāo):使得程序進(jìn)入播放器歌詞設(shè)置狀態(tài)前置條件:程序運(yùn)行在播設(shè)定界面基本事件流:1.用戶單擊“歌詞開關(guān)按鈕”按鈕2.播放器顯示或關(guān)閉歌詞3.1.4功能需求(時(shí)序圖)分析圖3.4音樂播放器的時(shí)序圖分析如(圖)3.2系統(tǒng)結(jié)構(gòu)圖和流程圖1.音樂播放器的系統(tǒng)流程圖(圖3.5)圖3.5音樂播放器系統(tǒng)流程圖2.系統(tǒng)功能表(表3.4)和系統(tǒng)功能結(jié)構(gòu)圖(圖3.6)表3.4播放器功能表功能類別子功能子功能播放列表播放列表菜單退出播放從擴(kuò)展卡尋找歌曲歌曲菜單播放->進(jìn)入播放界面刪除->數(shù)據(jù)庫同步更新重命名->數(shù)據(jù)庫同步更新向上、下移動(dòng)->數(shù)據(jù)庫同步更新播放界面播放播放歌曲->線程啟動(dòng)->時(shí)間更新暫停暫停歌曲->線程暫停->時(shí)間暫停停止停止歌曲->線程停止->時(shí)間停止上一首播放列表索引變化->尋找上一ID歌曲下一首播放列表索引變化->尋找下一ID歌曲播放界面菜單返回到播放列表返回到主菜單從擴(kuò)展卡尋找歌曲退出播放器隱藏播放界面主菜單退出程序程序退出進(jìn)入播放列表顯示播放列表圖3.6系統(tǒng)功能結(jié)構(gòu)圖3.3系統(tǒng)界面需求播放器界面要求布局合理,顏色舒適,控制按鈕友好。(圖3.7)圖3.7播放器界面3.4系統(tǒng)性能需求即使所寫代碼能夠通過世界上所有的性能測試,此時(shí)該應(yīng)用仍然有可能使用戶陷入狂暴狀態(tài)。例如缺乏響應(yīng)性、反應(yīng)慢、某些情況會卡、處理輸入的時(shí)間非常長的應(yīng)用就會使用戶體驗(yàn)大打折扣。在Android中,系統(tǒng)通過彈出一個(gè)“應(yīng)用無響應(yīng)(ANR)”對話框給用戶,來對抗一段時(shí)間沒有相應(yīng)的應(yīng)用。用戶可以在這個(gè)對話框中,選擇強(qiáng)制關(guān)閉還是等待。但是用戶不會喜歡在用你的應(yīng)用的時(shí)候總是看到這個(gè)對話框。所以,在你的應(yīng)用中設(shè)計(jì)響應(yīng)性是很重要的,系統(tǒng)就不會彈出ANR給用戶。一般來說,當(dāng)應(yīng)用對用戶輸入沒有相應(yīng)的時(shí)候,系統(tǒng)彈出ANR。例如,如果一個(gè)應(yīng)用阻塞在某些輸入輸出操作(例如頻繁地網(wǎng)絡(luò)請求),應(yīng)用的主線程就不會繼續(xù)響應(yīng)用戶的輸入事件。過了一段時(shí)間后,系統(tǒng)會認(rèn)為這個(gè)應(yīng)用已經(jīng)廢了,于是就彈出一個(gè)ANR來讓用戶選擇是否強(qiáng)制關(guān)閉應(yīng)用。在這種情況下,建立一個(gè)子線程來完成工作是常用的修復(fù)手段。這樣,主線程(響應(yīng)UI事件的循環(huán))就會一直運(yùn)行,系統(tǒng)就不會認(rèn)為你的代碼死了。一般來說,線程是屬于類級別,所以,你可以認(rèn)為響應(yīng)性是一個(gè)類級別的問題。因此根據(jù)Android手機(jī)系統(tǒng)要求無響應(yīng)時(shí)間為5秒,所以就有如下性能要求:1.當(dāng)要求歌曲播放時(shí),程序響應(yīng)時(shí)間最長不能超過5秒2.當(dāng)要求歌曲暫停時(shí),程序響應(yīng)時(shí)間最長不能超過5秒3.當(dāng)要求歌曲停止時(shí),程序響應(yīng)時(shí)間最長不能超過5秒4.當(dāng)要求歌曲上/下一首時(shí),程序響應(yīng)時(shí)間最長不能超過5秒5.當(dāng)要求進(jìn)行清單列表時(shí),程序響應(yīng)時(shí)間最長不能超過5秒下面談?wù)勅绾芜_(dá)到性能需求,即如何避免ANR、如何增加響應(yīng)性:3.4.1如何避免ANR通過上面給出的ANR的定義,為什么Android應(yīng)用會無響應(yīng),以與如何使你的應(yīng)用避免這個(gè)。一般來說,Android應(yīng)用會整個(gè)運(yùn)行在一個(gè)線程(主線程)里。這意味著,在主線程,任何需要很長時(shí)間完成的動(dòng)作,由于導(dǎo)致了你的應(yīng)用沒機(jī)會處理輸入事件或者廣播的Intent,都會觸發(fā)ANR對話框。因此,任何在主線程工作的方法,都應(yīng)該只做最少的事情。Activity的關(guān)鍵生命周期方法,例如onCreate()和onResume()里,更要做盡可能少的事。潛在的耗時(shí)運(yùn)算,例如網(wǎng)絡(luò)或數(shù)據(jù)庫操作,或者進(jìn)行類似縮放位圖這樣的大量的數(shù)學(xué)運(yùn)算,都應(yīng)該在子線程做。(對于數(shù)據(jù)庫操作,可以通過一個(gè)異步方法,而不必放進(jìn)另一個(gè)線程)。這并不意味著你的主線程應(yīng)該阻塞住等著子線程,無論是通過Thread.wait()還是Thread.sleep()。你的主線程應(yīng)該提供一個(gè)Handler來給子線程結(jié)束后返回結(jié)果。如此設(shè)計(jì)的應(yīng)用,可以讓主線程對輸入保持小于5秒的響應(yīng)速度,從而避免ANR對話框。如果其它的線程涉與展示UI,應(yīng)該遵循同樣的實(shí)踐。對IntentReceiver的執(zhí)行時(shí)間顯示,暗示了它應(yīng)該做的事情,是后臺小規(guī)模的工作,類似保存設(shè)置或者注冊Notification一類。所以,跟在主線程的方法一樣,應(yīng)用應(yīng)該避免在BroadcastReceiver中進(jìn)行潛在的耗時(shí)操作或運(yùn)算。除了在子線程中處理大量密集任務(wù)(因?yàn)锽roadcastReceiver生命周期是很短的)。當(dāng)一個(gè)潛在的耗時(shí)操作需要返回一個(gè)廣播Intent時(shí),此時(shí)應(yīng)用應(yīng)該啟動(dòng)一個(gè)

Service。另外,應(yīng)該避免從一個(gè)IntentReceiver里啟動(dòng)Activity,這將會跳出一個(gè)新的界面,并把用戶正在做的工作打斷。如果應(yīng)用收到廣播Intent之后需要展示給用戶什么的話,它應(yīng)該使用

NotificationManager。3.4.2增強(qiáng)響應(yīng)性一般來說,100到200毫秒是用戶感到“卡”的門檻。下面是避免ANR以與加快應(yīng)用響應(yīng)額外的方法。如果應(yīng)用需要等著后臺工作的結(jié)果(本應(yīng)用中網(wǎng)絡(luò)訪問較頻繁),此時(shí)應(yīng)在前臺展示出它的進(jìn)度。(可以使用ProgressBar或ProgressDialog)來實(shí)現(xiàn),如果你的應(yīng)用初始化耗時(shí)很長,考慮使用一個(gè)SplashScreen或者盡快進(jìn)入主界面然后再異步地慢慢填充。在這兩種情況,你應(yīng)該提供給用戶一個(gè)進(jìn)度條之類的東西,表明你的應(yīng)用還沒死。3.5運(yùn)行環(huán)境需求支持環(huán)境:AndroidSDK1.5以上4Android音樂播放器系統(tǒng)設(shè)計(jì)4.1音樂播放器界面功能實(shí)現(xiàn)音樂播放器界面用了TableHost組織5個(gè)Activity,每個(gè)Activity則用了Android5大布局(LinearLayout(線性布局)、FrameLayout(框架布局)、TableLayout(表格布局)、AbsoluteLayout(絕對位置布局)、RelativeLayout(相對位置布局))跟常用組件結(jié)合。下面是5個(gè)主要界面的運(yùn)行效果圖。圖4.1本地歌曲界面圖4.2在線音樂界面圖4.3播放界面圖4.4搜索界面圖4.5更多界面4.2本地音樂與網(wǎng)絡(luò)音樂播放功能實(shí)現(xiàn)本設(shè)計(jì)中播放音樂的功能主要是用到了AndroidSDK中的MediaPlayer類來實(shí)現(xiàn)播放音樂的功能。首先要做的是MediaPlayer對象的初始化。由于初始化可以由于種種原因不能成功(如文件無法讀取等),需要把它放在try塊中,并記錄可能出現(xiàn)的異常,根據(jù)異常做出相應(yīng)的處理。MediaPlayer對象在使用前要注意reset,因?yàn)樗鼤4嫔洗蔚牟シ艩顟B(tài)。Reset之后,就可以用setDataSource來設(shè)置多媒體文件的路徑了。這個(gè)路徑既可以是本地的,也可以是遠(yuǎn)程網(wǎng)絡(luò)上的。比如將一個(gè)協(xié)議下的音樂傳遞給MediaPlayer對旬,它能自動(dòng)下載緩沖播放遠(yuǎn)程文件。Prepare方法則是用于播放網(wǎng)絡(luò)上的音樂。比如在播放遠(yuǎn)程文件時(shí),使用該方法就會從遠(yuǎn)程獲取數(shù)據(jù)而不阻塞其它動(dòng)作。做好這些準(zhǔn)備后,就可以調(diào)用start方法,如果之前的狀態(tài)是暫停播放,start方法就會繼續(xù)播放(除非調(diào)用了reset方法),否則,它就會從頭開始播放音頻文件。為了解決自動(dòng)連接播放的問題,我們還要監(jiān)聽播放完畢這個(gè)事情,就是通過setOnCompletionListener方法設(shè)置一個(gè)監(jiān)聽器,監(jiān)聽到播放完成后就切換到下一曲繼續(xù)播放。另外幾個(gè)控制播放的方法也基本上都是對MediaPlayer對象的控制。在此不在贅述,詳細(xì)代碼請參見附錄。4.3數(shù)據(jù)存儲方式在播放器正常運(yùn)行時(shí),由于各界面存在相互跳轉(zhuǎn),為了避免數(shù)據(jù)在界面跳轉(zhuǎn)的過程中丟失,我們需要將一些數(shù)據(jù)進(jìn)行臨時(shí)存儲或者永久存儲。保存數(shù)據(jù)Android作為一種手機(jī)操作系統(tǒng),提供了如下幾種存取數(shù)據(jù)的方式:Preference(配置)、File(文件)、SQLite數(shù)據(jù)和網(wǎng)絡(luò)。保存數(shù)據(jù)另外,在Android中各個(gè)應(yīng)用程序組件之間是相互獨(dú)立的,彼此的數(shù)據(jù)不能共享。為了實(shí)現(xiàn)數(shù)據(jù)的共享,Android提供了ContentProvider組件來實(shí)現(xiàn)應(yīng)用程序之間數(shù)據(jù)的共享4.3.1SharedPreferencesShearedPreference提供了一種輕量級的數(shù)據(jù)存取方法,一般數(shù)據(jù)比較少,一些簡單的配置信息。它以“鍵-值”(是一個(gè)Map)對的方式,將數(shù)據(jù)保存在一個(gè)XML配置文件中。android.content.SharedPreferences提供了保存數(shù)據(jù)的方法android.content.SharedPreferences.Editor提供了獲得數(shù)據(jù)的方法1..xml配置文件的讀取我們?nèi)砸圆シ拍J阶x取為例:當(dāng)需要用到播放模式的確定時(shí),我們將讀取.Xml文件,同樣用共享文件類SharedPreferences通過用方法getSharedPreferences("SET_MSG",MODE_WORLD_READABLE),并且是只讀方式獲得.Xml的文件容。SharedPreferences的對象調(diào)用方法getString("sigle_Play",null),方法返回一個(gè)String類型的值,即是我們以前存儲進(jìn)去的String值。此方法當(dāng)該標(biāo)記不存在時(shí)會默認(rèn)返回一個(gè)null值。獲得成功后我們就可以運(yùn)用當(dāng)前的值再對程序進(jìn)行操作了。2..xml配置文件的存儲類SharedPreferences。它有一個(gè)方法getSharedPreferences(參數(shù)1,參數(shù)2),參數(shù)1為寫進(jìn)時(shí)的標(biāo)記,便于在從其中讀取出來時(shí)的標(biāo)記,參數(shù)2為讀取模式,有只寫模式(MODE_WORLD_WRITEABLE)和只讀模式(MODE_WORLD_READABLE),在寫之前將其置入編輯狀態(tài),用靜態(tài)方法SharedPreferences.Editoreditor=sp.edit();然后對象editor可以存入一個(gè)HashMap<key,values>類型的鍵值,即putString(KEY,VALUES),這樣,我們可以將List中的對象轉(zhuǎn)化成一樣長的字符中放進(jìn)配置文件中。當(dāng)寫入成功時(shí),android系統(tǒng)會自動(dòng)在目錄data/data/工程包名/shared_prefs/目錄下生成一個(gè)配置文件4.3.2File存儲方式我們可以將一些數(shù)據(jù)直接以文件的形式保存在設(shè)備中。例如,一些文本文件、PDF文件、音視頻文件和圖片等。Android提供了文件讀寫的方法方法Context.openFileInput()獲得標(biāo)準(zhǔn)Java文件輸入流(FileInputStream)方法Context.openFileOutput()獲得標(biāo)準(zhǔn)Java文件輸出流(FileOutputStream)Resources.openRawResource(R.raw.myDataFile)方法返回InputStream。4.3.3SQLiteDatabase數(shù)據(jù)庫SQLite是一個(gè)嵌入式數(shù)據(jù)庫引擎,針對存等資源有限的設(shè)備(如手機(jī)、PDA、MP3)提供的一種高效的數(shù)據(jù)庫引擎SQLite數(shù)據(jù)庫不像其它的數(shù)據(jù)庫(如:Oracle),它沒有服務(wù)器進(jìn)程。所有的容包含在同一個(gè)單文件中。該文件是跨平臺的可以自由拷貝。基于其自身的先天優(yōu)勢,SQLite在嵌入式領(lǐng)域得到了廣泛應(yīng)用。Android系統(tǒng)中使用Sqlite數(shù)據(jù)庫則是使用SQLiteDatabase類實(shí)現(xiàn)數(shù)據(jù)庫操作的。/data/data/package/shared_prefs/Android的三種數(shù)據(jù)存儲方式則讓我們可以輕松方便的進(jìn)行程序編寫和數(shù)據(jù)的訪問,更不會讓不該消失的數(shù)據(jù)消失,這對我們進(jìn)行程序書寫有很大我?guī)椭?data/data/package/shared_prefs/到這里,基于Android手機(jī)平臺的音樂播放器功能的介紹基本結(jié)束。5系統(tǒng)運(yùn)行與測試5.1調(diào)試工具介紹5.1.1通過Logcat來調(diào)試程序:Dump一份系統(tǒng)消息的日志.這些消息包括模擬器拋出錯(cuò)誤時(shí)的堆棧跟蹤.AndroidLog是一個(gè)記錄日志的類,用來將消息寫入模擬器上的日志文件中.如果你在DDMS上運(yùn)行l(wèi)ogcat的話你可以就實(shí)時(shí)查看消息.在你的代碼中加入幾個(gè)寫日志方法的調(diào)用。為了使用Log類,你只需要調(diào)用Log.v()(詳細(xì)),Log.d()(debug),Log.i()(information),Log.w()(warning)或者Log.e()(error),根據(jù)你想獲得的日志信息來選擇相應(yīng)的方法。在應(yīng)用程序中需要添加Log.i("MyActivity","MyClass.getView()—Requestingitemnumber"+position)這段代碼,就可以在logcat中讀取這些信息。5.1.2通過Traceview來調(diào)試程序:Android可以保存一個(gè)日志用來記錄被調(diào)用的方法以與該方法被調(diào)用的次數(shù),通過Traceview你可以在一個(gè)圖形化的界面中查看這個(gè)日志文件.5.1.3通過adb來調(diào)試程序:Android調(diào)試橋(adb)是多種用途的工具,該工具可以幫助你你管理設(shè)備或模擬器的狀態(tài).發(fā)出Android命令:你可以在你的開發(fā)機(jī)上的命令行或腳本上發(fā)布Android命令,使用方法:adb[-d|-e|-s<serialNumber>]<command>進(jìn)入Shell:adbshell查詢模擬器/設(shè)備實(shí)例adbdevices列出模擬器的序列號和狀態(tài)給特定的模擬器/設(shè)備實(shí)例發(fā)送命令如果有多個(gè)模擬器/設(shè)備實(shí)例在運(yùn)行,在發(fā)布adb命令時(shí)需要指定一個(gè)目標(biāo)實(shí)例.這樣做,請使用-s選項(xiàng)的命令.在使用的-s選項(xiàng)是adb-s<serialNumber><command>如:db-semulator-5556installhelloWorld.apk安裝軟件:adbinstall<path_to_apk>從模擬器/設(shè)備中拷入或拷出文件可以使用adbpull,push命令將文件復(fù)制到一個(gè)模擬器/設(shè)備實(shí)例的數(shù)據(jù)文件或是從數(shù)據(jù)文件中復(fù)制.install命令只將一個(gè).apk文件復(fù)制到一個(gè)特定的位置,與其不同的是,pull和push命令可令你復(fù)制任意的目錄和文件到一個(gè)模擬器/設(shè)備實(shí)例的任何位置.從模擬器或者設(shè)備中復(fù)制文件或目錄,使用(如下命):adbpull<remote><local>將文件或目錄復(fù)制到模擬器或者設(shè)備,使用(如下命令)adbpush<local><remote>在這些命令中,<local>和<remote>分別指通向自己的發(fā)展機(jī)(本地)和模擬器/設(shè)備實(shí)例(遠(yuǎn)程)上的目標(biāo)文件/目錄的路徑下面是一個(gè)例子:adbpushfoo.txt/sdcard/foo.txt查詢?nèi)罩綼dblogcatStoppingtheadbServer在某些情況下,你可能需要終止Android調(diào)試系統(tǒng)的運(yùn)行,然后再重新啟動(dòng)它.例如,如果Android調(diào)試系統(tǒng)不響應(yīng)命令,你可以先終止服務(wù)器然后再重啟,這樣就可能解決這個(gè)問題.用kill-server可以終止adbserver.你可以用adb發(fā)出start-server命令來重新啟動(dòng)服務(wù)器.5.2調(diào)試中出現(xiàn)的問題與解決方法本次應(yīng)用在編碼與調(diào)試過程中經(jīng)常出現(xiàn)有:空指針異常(NullPointerException)、類型強(qiáng)制轉(zhuǎn)換異常(ClassCastException)、數(shù)組下標(biāo)越界異常(ArrayIndexOutOfBoundsException)、文件未找到異常(FileNotFoundException)、輸入輸出異常(IOException)以與一些訪問權(quán)限等問題。有些比較容易解決,有的解決起來則較難,總之經(jīng)過不懈努力,終于將這些調(diào)試過程中出現(xiàn)的異常解決了,下面說說解決異常的方法:1.java.lang.nullpointerexception這個(gè)異常經(jīng)常遇到,異常的解釋是"程序遇上了空指針",簡單地說就是調(diào)用了未經(jīng)初始化的對象或者是不存在的對象,這個(gè)錯(cuò)誤經(jīng)常出現(xiàn)在創(chuàng)建變量、對象,調(diào)用數(shù)組這些操作中,比如對象未經(jīng)初始化,或者對象創(chuàng)建時(shí)的路徑錯(cuò)誤等等。對數(shù)組操作中出現(xiàn)空指針,很多情況下是把數(shù)組的初始化和數(shù)組元素的初始化混淆起來了。數(shù)組的初始化是對數(shù)組分配需要的空間,而初始化后的數(shù)組,其中的元素并沒有實(shí)例化,依然是空的,所以還需要對每個(gè)元素都進(jìn)行初始化(如果要調(diào)用的話)。2.java.lang.arrayindexoutofboundsexception這個(gè)異常相信很多朋友也經(jīng)常遇到過,異常的解釋是"數(shù)組下標(biāo)越界",現(xiàn)在程序多都有對數(shù)組的操作,因此在調(diào)用數(shù)組的時(shí)候一定要認(rèn)真檢查,看自己調(diào)用的下標(biāo)是不是超出了數(shù)組的圍,一般來說,顯示(即直接用常數(shù)當(dāng)下標(biāo))調(diào)用不太容易出這樣的錯(cuò),但隱式(即用變量表示下標(biāo))調(diào)用就經(jīng)常出錯(cuò)了,還有一種情況,是程序中定義的數(shù)組的長度是通過某些特定方法決定的,不是事先聲明的,這個(gè)時(shí)候,最好先查看一下數(shù)組的length,以免出現(xiàn)這個(gè)異常。其他還有很多異常,我就不一一列舉了,我要說明的是,一個(gè)合格的程序員,需要對程序中常見的問題有相當(dāng)?shù)牧私夂拖鄳?yīng)的解決辦法,否則僅僅停留在寫程序而不會改程序的話,會極大影響到自己的開發(fā)的。關(guān)于異常的全部說明,在api文檔里都可以查閱。還有遇到不會編寫的功能,或者功能塊有問題也可以借助一些論壇解決。5.3編譯運(yùn)行程序5.3.1編譯程序在Eclipse開發(fā)平臺中右擊Android工程,選擇RunasAndroidApplication即可編譯,編譯完成自動(dòng)打開模擬器(emulator-5554)運(yùn)行。5.3.2運(yùn)行程序Android程序的運(yùn)行一般有2種方法,即:模擬器運(yùn)行,真機(jī)運(yùn)行。1.模擬器運(yùn)行圖5.1模擬器運(yùn)行效果圖2.真機(jī)運(yùn)行將手機(jī)用數(shù)據(jù)線與電腦相連,安裝對應(yīng)手機(jī)型號的USB驅(qū)動(dòng),打開手機(jī)設(shè)置應(yīng)用程序開發(fā)USB調(diào)試后即可調(diào)試。右擊Android工程,選擇RunasAndroidAplication,由于已打開模擬器,需選擇在模擬器還是真機(jī)運(yùn)行,選擇真機(jī),確認(rèn)后系統(tǒng)將程序安裝到手機(jī)上,并自動(dòng)運(yùn)行。圖5.2為模擬器與真機(jī)選擇窗口,圖5.3為真機(jī)運(yùn)行效果,效果圖使用91助手刷新手機(jī)屏幕顯示截圖獲得。圖5.2模擬器與真機(jī)選擇界面圖5.391手機(jī)助手屏幕截圖5.4系統(tǒng)存在的不足由于時(shí)間的限制,本系統(tǒng)已經(jīng)完成了預(yù)期的大部分功能,但還有一些地方有待于進(jìn)一步的完善,系統(tǒng)的歌詞顯示未能完美實(shí)現(xiàn),部分歌曲歌詞不能呈現(xiàn),仍需要調(diào)試改進(jìn)。結(jié)論1.通過對Android手機(jī)平臺的音樂播放器軟件的開發(fā),使我對Android音樂播放器系統(tǒng)的整體設(shè)計(jì)有一個(gè)深入的了解,對整個(gè)流程也會有一個(gè)清晰的認(rèn)識。開發(fā)Android音樂播放器,要抓住開發(fā)的核心部分,音樂播放器大體由播放主界面、播放列表、菜單、播放設(shè)置、文件瀏覽、歌曲搜索六大核心組成,只要掌握了這六部分的開發(fā),音樂播放器就能初具規(guī)模。而其它的功能都是在這六個(gè)功能的基礎(chǔ)上去補(bǔ)充添加的,但是這些功能的確是必不可少的功能,否則就不能算是音樂播放器了。2.音樂播放器系統(tǒng)實(shí)現(xiàn)了播放器的基本功能:播放,暫停、停止、上/下一首、歌詞顯示、播放模式、歌曲搜索、文件瀏覽器、播放列表查詢等功能。運(yùn)用的系統(tǒng)平臺是現(xiàn)今最熱門的Android系統(tǒng),是一個(gè)開源的基于Linux系統(tǒng)的手機(jī)平臺。是以Java語言編寫+SQLite數(shù)據(jù)庫支持+SharedPreference配置文件的組合方式進(jìn)行數(shù)據(jù)管理。實(shí)現(xiàn)了音樂播放器的系統(tǒng)編程。3.本次程序設(shè)計(jì),對播放器的系統(tǒng)結(jié)構(gòu)框架做了精心的構(gòu)思與設(shè)計(jì),采用的開發(fā)語言是Java語言,采用主要開發(fā)工具是Eclipse,AndroidDevelopmentTool的插件,和AndroidSDK全面結(jié)合,才使整個(gè)音樂播放器系統(tǒng)得以實(shí)現(xiàn)。4.總之,經(jīng)過幾個(gè)月的Android系統(tǒng)技術(shù)知識的學(xué)習(xí)和對音樂播放器的構(gòu)思與設(shè)計(jì),使我對Android系統(tǒng)有了一定的了解,讓我對Android系統(tǒng)上的開發(fā)流程和開發(fā)模式有了深入的了解,這對我以后的Android項(xiàng)目開發(fā)有很大的幫助。在此論文抒寫過程中,我還要感我的指導(dǎo)老師給我的支持和建議。讓我能順利的完成本次論文。參考文獻(xiàn)[1]

Robi

Sen.Unlocking

Android:A

Developer’s

Guide[M].MANNING

PUBN.,2009.[2]

Sayed

Hashimi.Pro

Android

3[M].APRESS;NEW,2010.[3]

Marko

Gargenta.Learning

Android[M].O’REILLY&ASSOC

INC,2010.[4]

吳其慶.Java程序設(shè)計(jì)實(shí)例教程[M].:冶金工業(yè),2006.[5]文靖.Java程序設(shè)計(jì)基礎(chǔ)與上機(jī)指導(dǎo)[M].:清華大學(xué),2006.[6]

尚朗/靳巖.Google

Android開發(fā)入門與實(shí)踐[M].:人民郵電,2009.[

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論