Android項目之旅三 簡易Mp3播放器從獲取服務器端Mp3信息

   上面咱們已經把頁面弄好了,下面咱們就要在裏面實現咱們的功能了哦,今天主要是在RemoteMp3Activity中作功夫,由於項目啓動後,這個Activity要作不少事情哦:html

1)從服務器上面下載mp3.xml文件,將其轉化爲string格式;java

2)解析xml文件,這裏使用的是SAX解析技術,若是你們對XML和XML解析這部分不清楚的話,仍是老話,本身從網上查找相關的信息去學習一下,鍛鍊本身的自學能力;將解析出來的mp3信息轉換爲MP3對象,並保存在List集合中;android

3)在ListActivity中顯示出來;數組

好了,咱們分爲上面四步,那就咱們一步一步來吧!!服務器

1、從服務器上面下載mp3.xml文件,將其轉化爲string格式,咱們新建兩個類,一個類專門用來下載:HttpDownloader,一個類用來操做文件的輔助類,例如獲得SD卡的路徑,建立文件,判斷文件是否存在等等,取名爲FileUtils,先來開發咱們的HttpDownloader吧:app

public class HttpDownloader {  	private URL url=null;  	  	//下載文件,該文件主要是文本類型文件,返回其中的內容  	public String download(String urlStr){  		StringBuffer sb=new StringBuffer();  		String line=null;  		BufferedReader buffer=null;  		try {  			//建立一個URL對象  			url=new URL(urlStr);  			//建立一個Http鏈接  			HttpURLConnection urlConn=(HttpURLConnection)url.openConnection();  			//使用IO流讀取數據  			buffer=new BufferedReader(new InputStreamReader(urlConn.getInputStream()));  			while((line=buffer.readLine())!=null){  				sb.append(line);  			}  		} catch (MalformedURLException e) {  			e.printStackTrace();  		} catch (IOException e) {  			e.printStackTrace();  		}finally{  			try {  				buffer.close();  			} catch (IOException e) {  				e.printStackTrace();  			}  		}  		return sb.toString();  	}  }


這個方法的做用是從服務器上下載文本文件,並將其轉換爲String類型的字符串,在裏面一個重要的點事android提供的HttpURLConnection類,它能夠經過Url地址直接得到鏈接,而後進行相應的文件操做便可,經過傳入的地址參數,我這裏使用的地址是:http://192.168.1.104:8080/video/mp3.xml,將地址傳入過去,就能夠從服務器上獲得咱們想要的xml文件中的內容信息了!ide

2)解析XML字符串信息,將信息轉化爲對象保存在List集合中函數

首先咱們須要建立Mp3對象信息,取名爲Mp3Info,並生成其相應的get和set方法,重寫toString方法主要是方便項目的調試:佈局

package com.harderxin.model;    import java.io.Serializable;    public class Mp3Info implements Serializable{  	/**  	 *   	 */  	private static final long serialVersionUID = 1637894703074747542L;  	private String id;  	private String mp3Name;  	private String mp3Size;  	private String lrcName;  	private String lrcSize;  	  	public String getId() {  		return id;  	}  	public void setId(String id) {  		this.id = id;  	}  	public String getMp3Name() {  		return mp3Name;  	}  	public void setMp3Name(String mp3Name) {  		this.mp3Name = mp3Name;  	}  	public String getMp3Size() {  		return mp3Size;  	}  	public void setMp3Size(String mp3Size) {  		this.mp3Size = mp3Size;  	}  	public String getLrcName() {  		return lrcName;  	}  	public void setLrcName(String lrcName) {  		this.lrcName = lrcName;  	}  	public String getLrcSize() {  		return lrcSize;  	}  	public void setLrcSize(String lrcSize) {  		this.lrcSize = lrcSize;  	}  	@Override  	public String toString() {  		return "Mp3Info [id=" + id + ", mp3Name=" + mp3Name + ", mp3Size="  				+ mp3Size + ", lrcName=" + lrcName + ", lrcSize=" + lrcSize  				+ "]";  	}  }  


其次,咱們須要建立XML內容解析器,由於是SAX解析,咱們這裏繼承的類是DefaultHandler(爲何這麼作,這就跟SAX解析相關的知識點有關係哦),而後重寫裏面的方法,代碼裏面有相應的註釋哦:學習

package com.harderxin.utils;    import java.util.List;    import org.xml.sax.Attributes;  import org.xml.sax.SAXException;  import org.xml.sax.helpers.DefaultHandler;    import com.harderxin.model.Mp3Info;    /**   * 運用了一種適配器模式,由於DefaultHandler實現了ContentHandler接口   * 可是ContentHandler須要實現的方法不少,因此定義一個DefaultHandler   * 實現其中的方法,咱們只需繼承它覆寫咱們須要的方法便可   <resources>    <resource>      <id>1</id>  	<mp3.name>qmys.mp3</mp3.name>      <mp3.size>3557358</mp3.size>  	<lrc.name>qmys.lrc</lrc.name>  	<lrc.size>1294</lrc.size>    </resource>    <resource>      <id>2</id>  	<mp3.name>proud.mp3</mp3.name>      <mp3.size>3047992</mp3.size>  	<lrc.name>proud.lrc</lrc.name>  	<lrc.size>2078</lrc.size>    </resource>  </resources>   * @author Administrator   *   */  public class Mp3ListContentHandler extends DefaultHandler{      private String tagName;      private Mp3Info mp3Info;//定義一個全局變量的標籤名稱      private List<Mp3Info> mp3Infos;            //構造方法,將List集合傳入進去  	public Mp3ListContentHandler(List<Mp3Info> mp3Infos) {  		super();  		this.mp3Infos = mp3Infos;  	}    	//解析其中的文本<mp3.name>qmys.mp3</mp3.name>--->qmys.mp3  	@Override  	public void characters(char[] ch, int start, int length)  			throws SAXException {  		String temp=new String(ch,start,length);  		if(tagName.equals("id")){  			mp3Info.setId(temp);  		}else if(tagName.equals("mp3.name")){  			mp3Info.setMp3Name(temp);  		}else if(tagName.equals("mp3.size")){  			mp3Info.setMp3Size(temp);  		}else if(tagName.equals("lrc.name")){  			mp3Info.setLrcName(temp);  		}else if(tagName.equals("lrc.size")){  			mp3Info.setLrcSize(temp);  		}  	}    	@Override  	public void endDocument() throws SAXException {  		super.endDocument();  	}    	//解析結束元素  	@Override  	public void endElement(String uri, String localName, String qName)  			throws SAXException {  		if(localName.equals("resource")){  			mp3Infos.add(mp3Info);  		}  		tagName="";  	}    	//解析Document  	@Override  	public void startDocument() throws SAXException {  		//解析<resources>部分  		super.startDocument();  	}    	/**  	 * 解析Element  	 * namespaceURI 命名空間  	 * localName 不帶前綴部分<worker id="001">--->worker  	 * qName 帶前綴部分<abc:worker id="001">---->abc:worker  	 * attributes  屬性集合  <abc:worker id="001">---->id="001"....  	 */  	@Override  	public void startElement(String uri, String localName, String qName,  			Attributes attributes) throws SAXException {  		//解析<resource>部分  		tagName=localName;  		if(tagName.equals("resource")){  			mp3Info=new Mp3Info();  		}  	}  }  

上面解析後的xml文件將會轉換爲Mp3Info對象,最後保存在List集合中!

3)在ListActivity中顯示:

在RemoteMp3Activity中,咱們根據方法傳入相應的參數便可,由於程序中講究功能單一性,減小耦合,因此我把各部分的功能就用一個個方法在RemoteMp3Activity中寫出來:

根據地址從服務器獲取XML文件,將其轉內容換爲String類型:

	/**  	 * 從服務器上面獲取XML文件信息,並將其中信息轉換爲字符串  	 * @param url  	 * @return  	 */  	private String downLoadXML(String url){  		HttpDownloader httpDownloader=new HttpDownloader();  		String xmlStr=httpDownloader.download(url);  		return xmlStr;  	}


根據字符串解析出Mp3信息,將其轉換爲Mp3對象保存在List集合中:

	/**  	 * 解析XML文件,並將mp3Info信息放入到List集合中  	 * @param xmlStr  	 * @return  	 */  	private List<Mp3Info> parseXML(String xmlStr){  		List<Mp3Info> mp3Infos=new ArrayList<Mp3Info>();  		SAXParserFactory saxFactory=SAXParserFactory.newInstance();  		try {  			XMLReader xmlReader=saxFactory.newSAXParser().getXMLReader();  			xmlReader.setContentHandler(new Mp3ListContentHandler(mp3Infos));  			xmlReader.parse(new InputSource(new StringReader(xmlStr)));  		}catch(Exception e){  			e.printStackTrace();  		}  		return mp3Infos;  	}


創建SimpleAdapter對象,這裏須要跟你們說明一下,由於咱們繼承了ListActivity,其中的控件顯示方式如咱們之前看到的那種,就是一列一列的,它是經過咱們的代碼去控制的,須要創建一個SimpleAdapter對象,裏面須要幾個參數,你們還記得咱們在創建佈局文件的時候,創建過一個mp3_item.xml文件嗎,由於這裏就須要用到它,它是其中的一個參數,另外咱們還須要一個List<HashMap<String,String>>這樣一個對象,咱們得經過List<Mp3Info>去轉換,其中的HashMap<String,String>裏面的鍵值要和mp3_item.xml中的id值要同樣,至於爲何,那就要問android系統了,由於它裏面就是這樣規定的,咱們得按照它的要求來,若是你們仍是不懂的話,那就看一下android控件章節,ListActivity的案列吧,應該就明白了,我下面的代碼裏面也有註釋哦!

	/**  	 * 創建SimpleAdapter對象  	 * @param mp3Infos  	 * @return  	 */  	private SimpleAdapter buildSimpleAdapter(List<Mp3Info> mp3Infos){  		List<HashMap<String,String>> list=new ArrayList<HashMap<String,String>>();  		HashMap<String,String> map=null;  		//將List<Mp3Info>轉換爲List<HashMap<String,String>>對象  		//HashMap裏面的鍵值要和咱們的mp3_item.xml中的id同樣  		for(Mp3Info mp3Info:mp3Infos){  			map=new HashMap<String,String>();  			map.put("mp3_name", mp3Info.getMp3Name());  			map.put("mp3_size", mp3Info.getMp3Size());  			list.add(map);  		}  		//注意參數要一致,HashMap裏面的鍵值、參數中String數組、mp3_item.xml中的id要同樣  		SimpleAdapter simpleAdapter=new SimpleAdapter(RemoteMp3Activity.this,   				list, R.layout.mp3info_item,  				new String[]{"mp3_name","mp3_size"}, new int[]{R.id.mp3_name,R.id.mp3_size});  		return simpleAdapter;  	}


好了,上面三個函數都封裝好了,那就開始寫咱們的顯示頁面這個方法吧,就是一步一步去調用上面的幾個方法啦!

	/**  	 * 軟件中講究功能單一性,以方便代碼的重用,減小冗餘代碼  	 */  	private void updateListView(){  		String xmlStr=downLoadXML("http://192.168.1.104:8080/mp3/mp3.xml");  		mp3Infos=parseXML(xmlStr);  		SimpleAdapter simpleAdapter=buildSimpleAdapter(mp3Infos);  		setListAdapter(simpleAdapter);  	}


相信你們很容易弄懂,這樣寫就是方便調用,若是還有其餘地方須要這些重複的代碼,咱們只須要調用方法一次就能夠咯,減小代碼冗餘!

好了,接下來在咱們昨天寫的onCreate方法中調用顯示頁面這個方法吧!

  public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.remote_mp3_list);          updateListView();      }


這樣寫,是否是你們以爲代碼可複用性很高呢,之後寫代碼的時候要養成這樣的好習慣哦,不要在一個方法中寫處理太多邏輯的代碼,到時候可能形成同樣的功能咱們要寫不少重複的代碼,這是一個很很差的習慣,對之後程序的維護會形成不少很差的影響哦,因此你們得注意一下!!

最後還有一個事要作哦,就是咱們訪問服務器的時候,須要一個權限,另外,咱們訪問SD卡的時候也須要一個權限,否則android系統可不會讓你去直接操做哦,這個權限須要在AndroidMainifest.xml中進行配置,加上下面幾行代碼吧:

    <!-- 得到相應的權限 -->      <uses-permission android:name="android.permission.INTERNET"/>      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

上面分別表示得到外部訪問權限和SD卡的可讀訪問權限,必定要加上,否則會報錯!!

好了,代碼寫到這裏,咱們這部分功能就算完工咯,運行一下這個項目吧,保證咱們的Tomcat服務器是啓動的哦,咱們就能夠在模擬器上看到服務器上面的MP3文件的信息咯,我這裏顯示的是MP3文件的名稱和大小:

你們在實踐的過程當中,若是有什麼問題,或者你們有什麼意見,能夠給本博客留言哦,你們一塊兒交流分享,共同窗習,下一講我將會實現:點擊一個MP3文件,從服務器上找到相應的文件,下載到SD卡中,而後在LocalMp3Activity中顯示出來!!

相關文章
相關標籤/搜索