天天看点

系出名门Android(10) - HTTP 通信, XML 解析, 通过 Hander 实现异步消息处理

<a href="http://webabcd.blog.51cto.com/1787395/341976" target="_blank">[索引页]</a>

<a href="http://down.51cto.com/data/100088" target="_blank">[源码下载]</a>

系出名门Android(10) - HTTP 通信, XML 解析, 通过 Hander 实现异步消息处理

介绍

在 Android 中与服务端做 HTTP 通信,解析 XML,通过 Handler 实现异步消息处理

HTTP 通信 - 与服务端做 HTTP 通信,分别以 GET 方式和 POST 方式做演示

XML 解析 - 可以用两种方式解析 XML,分别是 DOM 方式和 SAX 方式

异步消息处理 - 通过 Handler 实现异步消息处理,以一个自定义的异步下载类来说明 Handler 的用法 

1、HTTP 通信和 XML 解析的 Demo

MySAXHandler.java

package com.webabcd.communication; 

import org.xml.sax.Attributes; 

import org.xml.sax.SAXException; 

import org.xml.sax.helpers.DefaultHandler; 

// 继承 DefaultHandler 以实现指定 XML 的 SAX 解析器 

// DOM - W3C 标准,需要把 xml 数据全部加载完成后才能对其做解析,可对树做任意遍历 

// SAX - 流式解析,通过事件模型解析 xml,只能顺序解析 

public class MySAXHandler extends DefaultHandler { 

        private boolean mIsTitleTag = false; 

        private boolean mIsSalaryTag = false; 

        private boolean mIsBirthTag = false; 

        private String mResult = ""; 

        // 打开 xml 文档的回调函数 

        @Override 

        public void startDocument() throws SAXException { 

                // TODO Auto-generated method stub 

                super.startDocument(); 

        } 

        // 关闭 xml 文档的回调函数 

        public void endDocument() throws SAXException { 

                super.endDocument(); 

        // 一发现元素开始标记就回调此函数 

        public void startElement(String uri, String localName, String qName, 

                        Attributes attributes) throws SAXException { 

                if (localName == "title") 

                        mIsTitleTag = true; 

                else if (localName == "salary") 

                        mIsSalaryTag = true; 

                else if (localName == "dateOfBirth") 

                        mIsBirthTag = true; 

                else if (localName == "employee") 

                        mResult += "\nname:" + attributes.getValue("name");         

        // 一发现元素结束标记就回调此函数 

        public void endElement(String uri, String localName, String qName) 

                        throws SAXException { 

                        mIsTitleTag = false; 

                        mIsSalaryTag = false; 

                        mIsBirthTag = false; 

        // 一发现元素值或属性值就回调此函数 

        public void characters(char[] ch, int start, int length) 

                if (mIsTitleTag) 

                        mResult += new String(ch, start, length); 

                else if (mIsSalaryTag) 

                        mResult += " salary:" + new String(ch, start, length); 

                else if (mIsBirthTag) 

                        mResult += " dateOfBirth:" + new String(ch, start, length); 

        public String getResult(){ 

                return mResult; 

}

Main.java

import java.io.BufferedInputStream; 

import java.io.BufferedReader; 

import java.io.IOException; 

import java.io.InputStream; 

import java.io.InputStreamReader; 

import java.net.HttpURLConnection; 

import java.net.URL; 

import java.net.URLConnection; 

import java.util.ArrayList; 

import java.util.HashMap; 

import java.util.Map; 

import javax.xml.parsers.DocumentBuilder; 

import javax.xml.parsers.DocumentBuilderFactory; 

import javax.xml.parsers.SAXParser; 

import javax.xml.parsers.SAXParserFactory; 

import org.apache.http.HttpEntity; 

import org.apache.http.HttpResponse; 

import org.apache.http.client.entity.UrlEncodedFormEntity; 

import org.apache.http.client.methods.HttpPost; 

import org.apache.http.impl.client.DefaultHttpClient; 

import org.apache.http.message.BasicNameValuePair; 

import org.apache.http.protocol.HTTP; 

import org.apache.http.util.ByteArrayBuffer; 

import org.apache.http.util.EncodingUtils; 

import org.w3c.dom.Document; 

import org.w3c.dom.Element; 

import org.w3c.dom.NodeList; 

import org.xml.sax.InputSource; 

import org.xml.sax.XMLReader; 

import android.app.Activity; 

import android.os.Bundle; 

import android.view.View; 

import android.widget.Button; 

import android.widget.TextView; 

public class Main extends Activity { 

        private TextView textView; 

        /** Called when the activity is first created. */ 

        public void onCreate(Bundle savedInstanceState) { 

                super.onCreate(savedInstanceState); 

                setContentView(R.layout.main); 

                textView = (TextView) this.findViewById(R.id.textView); 

                Button btn1 = (Button) this.findViewById(R.id.btn1); 

                btn1.setText("http get demo"); 

                btn1.setOnClickListener(new Button.OnClickListener() { 

                        public void onClick(View v) { 

                                httpGetDemo(); 

                        } 

                }); 

                Button btn2 = (Button) this.findViewById(R.id.btn2); 

                btn2.setText("http post demo"); 

                btn2.setOnClickListener(new Button.OnClickListener() { 

                                httpPostDemo(); 

                Button btn3 = (Button) this.findViewById(R.id.btn3); 

                // DOM - Document Object Model 

                btn3.setText("DOM 解析 XML"); 

                btn3.setOnClickListener(new Button.OnClickListener() { 

                                DOMDemo(); 

                Button btn4 = (Button) this.findViewById(R.id.btn4); 

                // SAX - Simple API for XML 

                btn4.setText("SAX 解析 XML"); 

                btn4.setOnClickListener(new Button.OnClickListener() { 

                                SAXDemo(); 

        // Android 调用 http 协议的 get 方法 

        // 本例:以 http 协议的 get 方法获取远程页面响应的内容 

        private void httpGetDemo(){ 

                try { 

                        // 模拟器测试时,请使用外网地址 

                        URL url = new URL("http://xxx.xxx.xxx"); 

                        URLConnection con = url.openConnection(); 

                        String result = "http status code: " + ((HttpURLConnection)con).getResponseCode() + "\n"; 

                        // HttpURLConnection.HTTP_OK 

                        InputStream is = con.getInputStream(); 

                        BufferedInputStream bis = new BufferedInputStream(is); 

                        ByteArrayBuffer bab = new ByteArrayBuffer(32); 

                        int current = 0; 

                        while ( (current = bis.read()) != -1 ){ 

                                bab.append((byte)current); 

                        result += EncodingUtils.getString(bab.toByteArray(), HTTP.UTF_8); 

                        bis.close(); 

                        is.close(); 

                        textView.setText(result); 

                } catch (Exception e) { 

                        textView.setText(e.toString()); 

                } 

        // Android 调用 http 协议的 post 方法 

        // 本例:以 http 协议的 post 方法向远程页面传递参数,并获取其响应的内容 

        private void httpPostDemo(){ 

                        String url = "http://5billion.com.cn/post.php"; 

                        Map&lt;String, String&gt; data = new HashMap&lt;String, String&gt;(); 

                        data.put("name", "webabcd"); 

                        data.put("salary", "100"); 

                        DefaultHttpClient httpClient = new DefaultHttpClient(); 

                        HttpPost httpPost = new HttpPost(url); 

                        ArrayList&lt;BasicNameValuePair&gt; postData = new ArrayList&lt;BasicNameValuePair&gt;(); 

                        for (Map.Entry&lt;String, String&gt; m : data.entrySet()) { 

                                postData.add(new BasicNameValuePair(m.getKey(), m.getValue())); 

                        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(postData, HTTP.UTF_8); 

                        httpPost.setEntity(entity); 

                        HttpResponse response = httpClient.execute(httpPost); 

                        String result = "http status code: " + response.getStatusLine().getStatusCode() + "\n"; 

                        HttpEntity httpEntity = response.getEntity(); 

                        InputStream is = httpEntity.getContent(); 

                        result += convertStreamToString(is); 

                        textView.setText(e.toString());         

        // 以 DOM 方式解析 XML(xml 数据详见 res/raw/employee.xml) 

        private void DOMDemo(){ 

                try        { 

                        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); 

                        DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); 

                        Document doc = docBuilder.parse(this.getResources().openRawResource(R.raw.employee)); 

                        Element rootElement = doc.getDocumentElement(); 

                        NodeList employeeNodeList = rootElement.getElementsByTagName("employee"); 

                        textView.setText("DOMDemo" + "\n"); 

                        String title = rootElement.getElementsByTagName("title").item(0).getFirstChild().getNodeValue(); 

                        textView.append(title); 

                        for (int i=0; i&lt;employeeNodeList.getLength(); i++){ 

                                Element employeeElement = ((Element)employeeNodeList.item(i)); 

                                String name = employeeElement.getAttribute("name"); 

                                String salary = employeeElement.getElementsByTagName("salary").item(0).getFirstChild().getNodeValue(); 

                                String dateOfBirth = employeeElement.getElementsByTagName("dateOfBirth").item(0).getFirstChild().getNodeValue(); 

                                textView.append("\nname: "+name+" salary: "+salary+" dateOfBirth: " + dateOfBirth); 

        // 以 SAX 方式解析 XML(xml 数据详见 res/raw/employee.xml) 

        // SAX 解析器的实现详见 MySAXHandler.java 

        private void SAXDemo(){ 

                        SAXParserFactory saxFactory = SAXParserFactory.newInstance(); 

                        SAXParser parser = saxFactory.newSAXParser(); 

                        XMLReader reader = parser.getXMLReader(); 

                        MySAXHandler handler = new MySAXHandler(); 

                        reader.setContentHandler(handler); 

                        reader.parse(new InputSource(this.getResources().openRawResource(R.raw.employee))); 

                        String result = handler.getResult(); 

                        textView.setText("SAXDemo" + "\n"); 

                        textView.append(result); 

        // 辅助方法,用于把流转换为字符串 

        private String convertStreamToString(InputStream is) { 

                BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 

                StringBuilder sb = new StringBuilder();        

                String line = null; 

                        while ((line = reader.readLine()) != null) { 

                                sb.append(line + "\n"); 

                } catch (IOException e) { 

                        e.printStackTrace(); 

                } finally { 

                        try { 

                                is.close(); 

                        } catch (IOException e) { 

                                e.printStackTrace(); 

                }        

                return sb.toString(); 

2、用 Handler 来实现异步消息处理,以一个可以实时汇报下载进度的异步下载类为例

开发一个 Android 类库,本例中此类库名为 webabcd_util

New -&gt; Java Project

项目上点右键 -&gt; Build Path -&gt; Add Libraries -&gt; User Library -&gt; User Libraries -&gt; New -&gt; 为类库起个名字 -&gt; 选中这个类库 -&gt; Add JARs 导入 Android 的 jar 包

项目上点右键 -&gt; Build Path -&gt; Add Libraries -&gt; User Library -&gt; 选择 Android 库

DownloadManagerAsync.java

package webabcd.util; 

import java.io.File; 

import java.io.FileOutputStream; 

import android.os.Handler; 

import android.os.Message; 

import android.util.Log; 

// 以一个实例,即异步下载,来演示 Android 的异步消息处理(用 Handler 的方式) 

public class DownloadManagerAsync { 

        public DownloadManagerAsync() { 

        // 实例化自定义的 Handler 

        EventHandler mHandler = new EventHandler(this); 

        // 按指定 url 地址下载文件到指定路径 

        public void download(final String url, final String savePath) { 

                new Thread(new Runnable() { 

                        public void run() { 

                                try { 

                                        sendMessage(FILE_DOWNLOAD_CONNECT); 

                                        URL sourceUrl = new URL(url); 

                                        URLConnection conn = sourceUrl.openConnection(); 

                                        InputStream inputStream = conn.getInputStream(); 

                                        int fileSize = conn.getContentLength(); 

                                        File savefile = new File(savePath); 

                                        if (savefile.exists()) { 

                                                savefile.delete(); 

                                        } 

                                        savefile.createNewFile(); 

                                        FileOutputStream outputStream = new FileOutputStream( 

                                                        savePath, true); 

                                        byte[] buffer = new byte[1024]; 

                                        int readCount = 0; 

                                        int readNum = 0; 

                                        int prevPercent = 0; 

                                        while (readCount &lt; fileSize &amp;&amp; readNum != -1) { 

                                                readNum = inputStream.read(buffer); 

                                                if (readNum &gt; -1) { 

                                                        outputStream.write(buffer); 

                                                        readCount = readCount + readNum; 

                                                        int percent = (int) (readCount * 100 / fileSize); 

                                                        if (percent &gt; prevPercent) { 

                                                                // 发送下载进度信息 

                                                                sendMessage(FILE_DOWNLOAD_UPDATE, percent, 

                                                                                readCount); 

                                                                prevPercent = percent; 

                                                        } 

                                                } 

                                        outputStream.close(); 

                                        sendMessage(FILE_DOWNLOAD_COMPLETE, savePath); 

                                } catch (Exception e) { 

                                        sendMessage(FILE_DOWNLOAD_ERROR, e); 

                                        Log.e("MyError", e.toString()); 

                                } 

                }).start(); 

        // 读取指定 url 地址的响应内容 

        public void download(final String url) { 

                                        conn.setConnectTimeout(3000); 

                                        BufferedReader reader = new BufferedReader( 

                                                        new InputStreamReader(conn.getInputStream(), 

                                                                        HTTP.UTF_8)); 

                                        String line = null; 

                                        StringBuffer content = new StringBuffer(); 

                                        while ((line = reader.readLine()) != null) { 

                                                content.append(line); 

                                        reader.close(); 

                                        sendMessage(FILE_DOWNLOAD_COMPLETE, content.toString()); 

        // 向 Handler 发送消息 

        private void sendMessage(int what, Object obj) { 

                // 构造需要向 Handler 发送的消息 

                Message msg = mHandler.obtainMessage(what, obj); 

                // 发送消息 

                mHandler.sendMessage(msg); 

        private void sendMessage(int what) { 

                Message msg = mHandler.obtainMessage(what); 

        private void sendMessage(int what, int arg1, int arg2) { 

                Message msg = mHandler.obtainMessage(what, arg1, arg2); 

        private static final int FILE_DOWNLOAD_CONNECT = 0; 

        private static final int FILE_DOWNLOAD_UPDATE = 1; 

        private static final int FILE_DOWNLOAD_COMPLETE = 2; 

        private static final int FILE_DOWNLOAD_ERROR = -1; 

        // 自定义的 Handler 

        private class EventHandler extends Handler { 

                private DownloadManagerAsync mManager; 

                public EventHandler(DownloadManagerAsync manager) { 

                        mManager = manager; 

                // 处理接收到的消息 

                @Override 

                public void handleMessage(Message msg) { 

                        switch (msg.what) { 

                        case FILE_DOWNLOAD_CONNECT: 

                                if (mOnDownloadConnectListener != null) 

                                        mOnDownloadConnectListener.onDownloadConnect(mManager); 

                                break; 

                        case FILE_DOWNLOAD_UPDATE: 

                                if (mOnDownloadUpdateListener != null) 

                                        mOnDownloadUpdateListener.onDownloadUpdate(mManager, 

                                                        msg.arg1); 

                        case FILE_DOWNLOAD_COMPLETE: 

                                if (mOnDownloadCompleteListener != null) 

                                        mOnDownloadCompleteListener.onDownloadComplete(mManager, 

                                                        msg.obj); 

                        case FILE_DOWNLOAD_ERROR: 

                                if (mOnDownloadErrorListener != null) 

                                        mOnDownloadErrorListener.onDownloadError(mManager, 

                                                        (Exception) msg.obj); 

                        default: 

        // 定义连接事件 

        private OnDownloadConnectListener mOnDownloadConnectListener; 

        public interface OnDownloadConnectListener { 

                void onDownloadConnect(DownloadManagerAsync manager); 

        public void setOnDownloadConnectListener(OnDownloadConnectListener listener) { 

                mOnDownloadConnectListener = listener; 

        // 定义下载进度更新事件 

        private OnDownloadUpdateListener mOnDownloadUpdateListener; 

        public interface OnDownloadUpdateListener { 

                void onDownloadUpdate(DownloadManagerAsync manager, int percent); 

        public void setOnDownloadUpdateListener(OnDownloadUpdateListener listener) { 

                mOnDownloadUpdateListener = listener; 

        // 定义下载完成事件 

        private OnDownloadCompleteListener mOnDownloadCompleteListener; 

        public interface OnDownloadCompleteListener { 

                void onDownloadComplete(DownloadManagerAsync manager, Object result); 

        public void setOnDownloadCompleteListener( 

                        OnDownloadCompleteListener listener) { 

                mOnDownloadCompleteListener = listener; 

        // 定义下载异常事件 

        private OnDownloadErrorListener mOnDownloadErrorListener; 

        public interface OnDownloadErrorListener { 

                void onDownloadError(DownloadManagerAsync manager, Exception e); 

        public void setOnDownloadErrorListener(OnDownloadErrorListener listener) { 

                mOnDownloadErrorListener = listener; 

调用上面的自定义的 Android 类库

项目上点右键 -&gt; Properties -&gt; Java Build Path -&gt; Projects -&gt; Add 引用上面的类库

package com.webabcd.handler; 

import webabcd.util.DownloadManagerAsync; 

public class Main extends Activity implements 

                DownloadManagerAsync.OnDownloadCompleteListener, 

                DownloadManagerAsync.OnDownloadUpdateListener, 

                DownloadManagerAsync.OnDownloadErrorListener { 

        TextView txt; 

                DownloadManagerAsync manager = new DownloadManagerAsync(); 

                manager.setOnDownloadCompleteListener(this); 

                manager.setOnDownloadUpdateListener(this); 

                manager.download("http://files.cnblogs.com/webabcd/Android.rar", "/sdcard/Android.rar"); 

                txt = (TextView) this.findViewById(R.id.txt); 

                txt.setText("开始下载"); 

        public void onDownloadComplete(DownloadManagerAsync manager, Object result) { 

                txt.setText("下载完成"); 

        public void onDownloadUpdate(DownloadManagerAsync manager, int percent) { 

                txt.setText("下载进度:" + String.valueOf(percent) + "%"); 

        public void onDownloadError(DownloadManagerAsync manager, Exception e) { 

                txt.setText("下载出错"); 

OK

     本文转自webabcd 51CTO博客,原文链接:http://blog.51cto.com/webabcd/342102,如需转载请自行联系原作者

继续阅读