《電子技術應用》
您所在的位置:首頁 > 嵌入式技術 > 設計應用 > 基于Android系統(tǒng)的音樂播放器設計與實現(xiàn)
基于Android系統(tǒng)的音樂播放器設計與實現(xiàn)
來源:微型機與應用2014年第1期
葛 艷,高占江
(青島科技大學 信息科學技術學院,山東 青島 266061)
摘要: 基于Android平臺開發(fā)音樂播放器。該播放器主要實現(xiàn)了SD卡掃描、后臺播放、歌手與專輯篩選,歌曲列表管理、歌詞同步滾動顯示、播放模式選擇、皮膚更換、網(wǎng)絡下載、桌面Widget等功能。對Android應用程序的開發(fā)環(huán)境及工具作了簡單介紹,詳細介紹了音樂播放器軟件界面布局方式、自動音樂掃描機制、歌詞同步實現(xiàn)算法以及歌詞的搜索與下載等功能模塊的設計與實現(xiàn)。對歌詞同步滾動顯示進行了透徹分析。該音樂播放器通過了Android智能手機運行測試,具有較好的集成度和良好的穩(wěn)定性。
Abstract:
Key words :

摘  要: 基于Android平臺開發(fā)音樂播放器。該播放器主要實現(xiàn)了SD卡掃描、后臺播放、歌手與專輯篩選,歌曲列表管理、歌詞同步滾動顯示、播放模式選擇、皮膚更換、網(wǎng)絡下載、桌面Widget等功能。對Android應用程序的開發(fā)環(huán)境及工具作了簡單介紹,詳細介紹了音樂播放器軟件界面布局方式、自動音樂掃描機制、歌詞同步實現(xiàn)算法以及歌詞的搜索與下載等功能模塊的設計與實現(xiàn)。對歌詞同步滾動顯示進行了透徹分析。該音樂播放器通過了Android智能手機運行測試,具有較好的集成度和良好的穩(wěn)定性。
關鍵詞: Android;Java;音樂播放;歌詞同步

 隨著科技發(fā)展的日新月異,人們對移動設備的需求越來越高,手機已不只是通信工具,而是一個多媒體平臺。Android是Google公司開發(fā)的基于Linux平臺的開源的移動終端智能操作系統(tǒng)[1]。Android系統(tǒng)由操作系統(tǒng)、用戶界面和應用程序組成,允許開發(fā)人員自由獲取和修改源代碼。Android的發(fā)布大大豐富了各種手持式設備軟件的功能[2]。
 本文基于Android平臺開發(fā)音樂播放器,選擇開發(fā)個性的播放軟件,摒棄單方面追求花哨而帶來的系統(tǒng)資源浪費,將各種性能優(yōu)化,繼承播放器的常用功能,滿足大多數(shù)用戶的娛樂需求。該播放器實現(xiàn)SD卡掃描、后臺播放、歌手與專輯篩選,歌曲列表管理、歌詞同步滾動顯示、播放模式選擇、皮膚更換、網(wǎng)絡下載等功能。此外,還實現(xiàn)桌面的Widget功能,使用戶在不打開該軟件的同時,就可以一鍵聽歌,極大地優(yōu)化了用戶體驗。
1 Android簡介
 Android系統(tǒng)分為Applications、Application Framework、Libraries、Android Runtime、Linux Kernel 5大層[3]。本播放軟件屬于應用軟件,只對Applications應用層程序的探討,對具體壓縮算法不作深究。
1.1 Android基本組件
 Android應用程序的組件主要有4個,針對智能手機的諸多突發(fā)情形,都做出了相應的處理操作[4]。
    (1)Activity:是應用程序最基本的組件。應用程序的每個頁面都由各種Activity構成。它是一種可視化的、直接與用戶接觸的界面元素。
?。?)Service:是一種服務組件,運行于程序的后臺。該組件對用戶是不可見的,在后臺提供程序的托管運行。
?。?)ContentProvider:是一種內容提供者組件。該組件能夠實現(xiàn)應用程序之間的數(shù)據(jù)共享,并能夠監(jiān)聽其共享數(shù)據(jù)的變化。
?。?)BroadcastReceiver:實現(xiàn)應用程序內部數(shù)據(jù)的傳遞,也能實現(xiàn)事件的先后順序觸發(fā)。
1.2 開發(fā)工具
 軟件開發(fā)使用Eclipse軟件,使用Android SDK、ADT的支持,JDK開發(fā)環(huán)境,使用Java語言作為開發(fā)語言,基于C/S開發(fā)模式。使用Emulator調試工具,調試工具提供了斷點調試,文件管理,電話短信模擬,在軟件開發(fā)過程中提供了極大的方便。
2 軟件核心功能
 該部分詳細介紹了播放界面的布局方式、音樂列表自動掃描原理、播放時歌詞同步滾動實現(xiàn)機制、歌詞搜索與下載機制。
2.1 主頁面布局
 軟件的主播放界面采用線性布局與層疊布局的結合,布局中使用了Android的系統(tǒng)控件和自定義的控件,豐富了頁面元素,并對每個控件進行了布局設置,下面對應播放主界面的布局:
 //線性布局方式
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:lrcview="http://schemas.android.com/apk/res/com.gao.mymediaplayer01"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <FrameLayout //層疊布局方式
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <ImageView //圖片控件
            android:id="@+id/background"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_gravity="fill"/>
  //下面是自定義歌詞控件的布局控制
  <com.gao.mymediaplayer01.LrcView
 //自定義歌詞控件類
 android:id="@+id/lrcTextView"//控件的唯一標識(Id)
 android:layout_width="fill_parent"
 //設置控件的寬度填充父控件
 android:layout_height="160dip"
 //設置控件的高度為特定值
 android:gravity="center"
 //設置控件內容的對齊方式為居中
 android:layout_gravity="center_horizontal"
 //控件的對齊方式為水平居中
 android:layout_marginTop="70dip"
 //控件垂直方向上距離頂部的距離
 />........................其他控件........................
 上面是頁面布局的部分代碼,最后一個控件com.gao.mymediaplayer01.LrcView使用的是自定義的控件,目的是顯示歌詞信息并能夠根據(jù)歌曲當前播放時間匹配歌詞的當前行索引,實現(xiàn)歌詞的實時動態(tài)刷新顯示。實現(xiàn)的效果如圖1所示。
2.2 音樂掃描
 Android系統(tǒng)提供了一種類似關系表的結構來把應用程序的數(shù)據(jù)暴露給外界,并把每個這種表使用唯一的標識符URI來標識[2]。Android系統(tǒng)對外部存儲設備的媒體文件進行了統(tǒng)一管理,把每個音樂文件的ID、時長、藝術家等相關信息全部存放在這個表中,使用Contentprovider來訪問這個唯一的標識符URI便可以查詢到在用戶的SD卡中的所有的音樂文件,實現(xiàn)代碼如下:
musicCursor=this.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Audio.Media.TITLE,//歌曲標題
MediaStore.Audio.Media.DURATION,//歌曲時長
MediaStore.Audio.Media.ARTIST,//歌曲的作者
MediaStore.Audio.Media._ID,
//歌曲在SD卡上的唯一標識
MediaStore.Audio.Media.DISPLAY_NAME,
//歌曲顯示的名字
MediaStore.Audio.Media.DATA//歌曲文件的路徑
},null,null,null);
 根據(jù)查詢條件可以得到所有歌曲的游標指針,這里的查詢條件可以設置指定的藝術家和指定的專輯,從而可以查詢指定的藝術家和專輯的特定歌曲列表。將得到的游標數(shù)據(jù)傳遞到ListAdapter適配器中,其中可以設置列表項顯示的內容,之后為這個ListView控件設置單擊事件。
2.3 歌詞同步滾動實現(xiàn)機制
 音樂播放時實現(xiàn)歌詞同步滾動顯示是本音樂播放器的一個特色。下面詳細介紹實現(xiàn)歌詞同步滾動的具體流程:
 (1)歌詞LRC文件一般存放在與該歌曲相同的位置,通過歌曲在SD卡上的DATA屬性獲得LRC文件的位置,使用輸入緩沖流BufferedReader進行讀取,關鍵是每一次讀取歌詞文件的一行,因為歌詞文件的每一行是一個或者多個時刻和歌詞內容的連接,這里把每行歌詞抽象為一個對象,整個歌詞文件看成是所有對象的List集合,每個對象是由時間屬性和歌詞內容屬性共同組成,在讀取每一行歌詞并將其轉換成歌詞類的一個實例時,對不同的表示形式作了不同的處理:
 [00:25.93]和[00:25]兩種時間形式的處理。對其統(tǒng)一格式后判斷時間段的長度,采用不同的函數(shù)處理。在實際使用時將其轉換為毫秒保存到對象的時間的私有變量中,內容保存到LRC內容的成員變量中。
對于在一行歌詞中多個時間段表示同一種歌詞內容的情形,首先對整行歌詞中的字符“]”統(tǒng)一替換為某個特殊的字符,將整行內容根據(jù)這個特殊字符進行分割得到string類型的數(shù)組:String[]splitLrc_data=str.split("@");可以得到數(shù)組長度減一個數(shù)量的歌詞對象,每個歌詞對象時間域為分割得到的數(shù)組的內容,內容域都是數(shù)組最后一個元素的值,最后將所有這些歌詞對象存放到List<LrcContent>當中。
?。?)對List歌詞對象按照其時間變量進行排序,排序采用冒泡排序算法,其核心代碼如下:
for(int i=1;i<=count-1;i++)
for(int j=0;j<count-i;j++)
{//排序依據(jù)是歌詞對象的時間變量
if(LrcList.get(j).getLrc_time()>LrcList.get(j+1).getLrc_time())
{
LrcContent tempLrcContent=LrcList.set(j,LrcList.get(j+1));
LrcList.set(j+1,tempLrcContent);
}}
?。?)利用冒泡排序算法最終得到按時間先后排好序的歌詞對象的List,根據(jù)歌曲當前播放時間選擇當前需要顯示的歌詞行的索引,具體操作如下。
當前歌曲時間小于第一個歌詞對象的時間時,設定要顯示歌詞的行的索引為1;
當前歌曲時間大于第一個歌詞對象的時間時,要循環(huán)判斷出當前歌詞時間大于第N個歌詞對象的時間并且要小于第N+1個歌詞對象的時間,設定要顯示的歌詞的行的索引為N;
 當前歌曲時間大于最后一個歌詞行的時間時,設定要顯示的歌詞行的索引為歌詞文件的數(shù)量。
?。?)最后,得到當前顯示歌詞的索引后,使用自定義文本控件高亮顯示當前歌詞行,其余歌詞行非高亮顯示。在后臺Service中設定刷新頻率為50 ms,每50 ms獲得當前歌曲時間進度,更新當前行的索引,獲得一個時刻的當前行的索引后,從Service中利用廣播機制將其發(fā)送到前臺Activity中,在Activity接收到當前索引后,將自定義的歌詞控件重新繪出。
 設置lrcView.setIndex(lrcIndex)后,使用lrcView.invalidate()強制使歌詞控件重新繪畫,此時繪出的高亮行為當前索引行,且顯示在屏幕的中央,其余行顯示為非高亮行,繪畫歌詞的算法核心代碼如下:
canvas.drawText(lrcList.get(Index).getLrc_body(),width/2,high/2,
CurrentPaint);
float tempY=high/2;//屏幕垂直方向中央的高度
//畫出本句之前的句子
for(int i=Index-1;i>=0;i--){
tempY=tempY-TextHigh;
canvas.drawText(lrcList.get(i).getLrc_body(),width/2,tempY,NotCurrentPaint);}
tempY=high/2;
//畫出本句之后的句子
for(int i=Index+1;i<=lrcList.size()-1;i++){
tempY=tempY+TextHigh;
canvas.drawText(lrcList.get(i).getLrc_body(),width/2,tempY,NotCurrentPaint);}
 按照上述步驟,在后臺Service中設定刷新頻率(一般為50~200 ms)可以實現(xiàn)動態(tài)的顯示歌詞。歌詞滾動效果如圖1所示。

2.4 歌詞的搜索與下載

 


 要下載一首歌的歌詞信息,應該由這首歌曲的歌手和歌曲名共同決定,所以利用當前播放歌曲的歌手和歌曲名稱作為參數(shù)進行歌詞的搜索,這里使用百度音樂盒提供的歌詞服務器來進行下載。下載流程如下:
 (1)首先將歌曲的歌手和歌曲名稱進行UTF-8編碼的轉換如下:
 titleName=URLEncoder.encode(titleName,"UTF-8");
singerName=URLEncoder.encode(singerName,"UTF-8");
?。?)其次,將參數(shù)傳遞到搜索鏈接中:
 strUrl="http://box.zhangmen.baidu.com/x?op=12&count=1&title="+titleName+"$$"+singerName+"$$$$";
此鏈接指向的是一個xml類型的文件,該文件包含對該歌曲及歌詞等信息的描述,使用I/O流讀取該文件,如果該文件內容不為空,可以從中獲取到該歌詞在服務器中的Id(即LyricId),根據(jù)這個Id,如果這個Id不為空,進而可以得到該歌詞文件的URL鏈接地址:
 lyricURLStr="http://box.zhangmen.baidu.com/bdlrc/"+lyricId/100+"/"+lyricId+".lrc";
根據(jù)該URL使用I/O流將歌詞文件下載到本地就可以完成歌詞的下載。
?。?)最后,歌詞下載完成后,獲取歌詞的保存路徑,調用解析歌詞文件的方法進行解析實現(xiàn)歌詞的滾動顯示。
 本文介紹了基于Android平臺的音樂播放器的設計方案和關鍵技術。詳細介紹了音樂播放器軟件界面布局方式、自動音樂掃描機制、歌詞同步實現(xiàn)算法以及歌詞的搜索與下載等功能模塊的設計與實現(xiàn)。對歌詞同步滾動顯示進行了透徹分析。該音樂播放器集掃描SD卡,音樂列表顯示、播放、后臺播放、上一首、下一首、音量調節(jié)歌手選擇、專輯選擇、最近播放、最經(jīng)常播放、歌詞同步滾動顯示、快進快退、播放模式選擇、更換皮膚、音樂文件操作、網(wǎng)絡下載、桌面Widget等功能于一體,功能較完善。通過在Android智能手機對音樂播放器進行了功能測試。該音樂播放器性能良好,運行流暢。
參考文獻
[1] 周時偉,謝維波.基于Android的智能家居終端設計與實現(xiàn)[J].微型機與應用,2012,31(14):10-13.
[2] 曾建平,邵艷潔.Android系統(tǒng)架構及應用程序開發(fā)研究[J].微計算機信息,2011,27(9):1-3.
[3] 樊新,高曙.基于智能移動終端的安全檢查系統(tǒng)設計與實現(xiàn)[J].微型機與應用,2012,31(20):87-92.
[4] 劉安戰(zhàn),賈曉輝.基于Android的私密短信系統(tǒng)設計與實現(xiàn)[J].微型機與應用,2012,31(17):51-56.

此內容為AET網(wǎng)站原創(chuàng),未經(jīng)授權禁止轉載。