Android项目之旅三 简易Mp3播放器从获取服务器端Mp3信息

   上面我们已经把页面弄好了,下面我们就要在里面实现我们的功能了哦,今天主要是在RemoteMp3Activity中做功夫,因为项目启动后,这个Activity要做很多事情哦:

1)从服务器上面下载mp3.xml文件,将其转化为string格式;

2)解析xml文件,这里使用的是SAX解析技术,如果大家对XML和XML解析这部分不清楚的话,还是老话,自己从网上查找相关的信息去学习一下,锻炼自己的自学能力;将解析出来的mp3信息转换为MP3对象,并保存在List集合中;

3)在ListActivity中显示出来;

好了,我们分为上面四步,那就我们一步一步来吧!!

一、从服务器上面下载mp3.xml文件,将其转化为string格式,我们新建两个类,一个类专门用来下载:HttpDownloader,一个类用来操作文件的辅助类,例如得到SD卡的路径,创建文件,判断文件是否存在等等,取名为FileUtils,先来开发我们的HttpDownloader吧:

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文件中的内容信息了!

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文件的名称和大小:

Android项目之旅三 简易Mp3播放器从获取服务器端Mp3信息_第1张图片

大家在实践的过程中,如果有什么问题,或者大家有什么意见,可以给本博客留言哦,大家一起交流分享,共同学习,下一讲我将会实现:点击一个MP3文件,从服务器上找到相应的文件,下载到SD卡中,然后在LocalMp3Activity中显示出来!!

你可能感兴趣的:(Android项目之旅三 简易Mp3播放器从获取服务器端Mp3信息)