HTTP 通信, 三种方式XML 解析,并通过 Hander 实现异步消息处理

来源:互联网 发布:珠海网络 编辑:程序博客网 时间:2024/04/21 00:11

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

作者:webabcd

介绍
在 Android 中与服务端做 HTTP 通信,解析 XML,通过 Handler 实现异步消息处理
HTTP 通信 - 与服务端做 HTTP 通信,分别以 GET 方式和 POST 方式做演示
XML 解析 - 可以用两种方式解析 XML,分别是 DOM 方式和 SAX 方式
异步消息处理 - 通过 Handler 实现异步消息处理,以一个自定义的异步下载类来说明 Handler 的用法 


1、HTTP 通信和 XML 解析的 Demo
MySAXHandler.java

Java代码  收藏代码
  1. 代码   
  2. package com.webabcd.communication;  
  3.   
  4. import org.xml.sax.Attributes;  
  5. import org.xml.sax.SAXException;  
  6. import org.xml.sax.helpers.DefaultHandler;  
  7.   
  8. // 继承 DefaultHandler 以实现指定 XML 的 SAX 解析器  
  9. // DOM - W3C 标准,需要把 xml 数据全部加载完成后才能对其做解析,可对树做任意遍历  
  10. // SAX - 流式解析,通过事件模型解析 xml,只能顺序解析  
  11. public class MySAXHandler extends DefaultHandler {  
  12.   
  13.     private boolean mIsTitleTag = false;  
  14.     private boolean mIsSalaryTag = false;  
  15.     private boolean mIsBirthTag = false;  
  16.     private String mResult = "";  
  17.       
  18.     // 打开 xml 文档的回调函数  
  19.     @Override  
  20.     public void startDocument() throws SAXException {  
  21.         // TODO Auto-generated method stub  
  22.         super.startDocument();  
  23.     }  
  24.       
  25.     // 关闭 xml 文档的回调函数  
  26.     @Override  
  27.     public void endDocument() throws SAXException {  
  28.         // TODO Auto-generated method stub  
  29.         super.endDocument();  
  30.     }  
  31.       
  32.     // 一发现元素开始标记就回调此函数  
  33.     @Override  
  34.     public void startElement(String uri, String localName, String qName,  
  35.             Attributes attributes) throws SAXException {  
  36.         if (localName == "title")  
  37.             mIsTitleTag = true;  
  38.         else if (localName == "salary")  
  39.             mIsSalaryTag = true;  
  40.         else if (localName == "dateOfBirth")  
  41.             mIsBirthTag = true;  
  42.         else if (localName == "employee")  
  43.             mResult += "\nname:" + attributes.getValue("name");      
  44.     }  
  45.   
  46.     // 一发现元素结束标记就回调此函数  
  47.     @Override  
  48.     public void endElement(String uri, String localName, String qName)  
  49.             throws SAXException {  
  50.         if (localName == "title")  
  51.             mIsTitleTag = false;  
  52.         else if (localName == "salary")  
  53.             mIsSalaryTag = false;  
  54.         else if (localName == "dateOfBirth")  
  55.             mIsBirthTag = false;  
  56.     }  
  57.   
  58.     // 一发现元素值或属性值就回调此函数  
  59.     @Override  
  60.     public void characters(char[] ch, int start, int length)  
  61.             throws SAXException {  
  62.         if (mIsTitleTag)  
  63.             mResult += new String(ch, start, length);  
  64.         else if (mIsSalaryTag)  
  65.             mResult += " salary:" + new String(ch, start, length);  
  66.         else if (mIsBirthTag)  
  67.             mResult += " dateOfBirth:" + new String(ch, start, length);  
  68.     }  
  69.       
  70.     public String getResult(){  
  71.         return mResult;  
  72.     }  
  73. }  
  74.   
  75.   
  76. Main.java  
  77.   
  78. 代码   
  79. package com.webabcd.communication;  
  80.   
  81. import java.io.BufferedInputStream;  
  82. import java.io.BufferedReader;  
  83. import java.io.IOException;  
  84. import java.io.InputStream;  
  85. import java.io.InputStreamReader;  
  86. import java.net.HttpURLConnection;  
  87. import java.net.URL;  
  88. import java.net.URLConnection;  
  89. import java.util.ArrayList;  
  90. import java.util.HashMap;  
  91. import java.util.Map;  
  92.   
  93. import javax.xml.parsers.DocumentBuilder;  
  94. import javax.xml.parsers.DocumentBuilderFactory;  
  95. import javax.xml.parsers.SAXParser;  
  96. import javax.xml.parsers.SAXParserFactory;  
  97.   
  98. import org.apache.http.HttpEntity;  
  99. import org.apache.http.HttpResponse;  
  100. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  101. import org.apache.http.client.methods.HttpPost;  
  102. import org.apache.http.impl.client.DefaultHttpClient;  
  103. import org.apache.http.message.BasicNameValuePair;  
  104. import org.apache.http.protocol.HTTP;  
  105. import org.apache.http.util.ByteArrayBuffer;  
  106. import org.apache.http.util.EncodingUtils;  
  107. import org.w3c.dom.Document;  
  108. import org.w3c.dom.Element;  
  109. import org.w3c.dom.NodeList;  
  110. import org.xml.sax.InputSource;  
  111. import org.xml.sax.XMLReader;  
  112.   
  113. import android.app.Activity;  
  114. import android.os.Bundle;  
  115. import android.view.View;  
  116. import android.widget.Button;  
  117. import android.widget.TextView;  
  118.   
  119. public class Main extends Activity {  
  120.       
  121.     private TextView textView;  
  122.       
  123.     /** Called when the activity is first created. */  
  124.     @Override  
  125.     public void onCreate(Bundle savedInstanceState) {  
  126.         super.onCreate(savedInstanceState);  
  127.         setContentView(R.layout.main);  
  128.           
  129.         textView = (TextView) this.findViewById(R.id.textView);  
  130.           
  131.         Button btn1 = (Button) this.findViewById(R.id.btn1);  
  132.         btn1.setText("http get demo");  
  133.         btn1.setOnClickListener(new Button.OnClickListener() {  
  134.             public void onClick(View v) {  
  135.                 httpGetDemo();  
  136.             }  
  137.         });  
  138.           
  139.         Button btn2 = (Button) this.findViewById(R.id.btn2);  
  140.         btn2.setText("http post demo");  
  141.         btn2.setOnClickListener(new Button.OnClickListener() {  
  142.             public void onClick(View v) {  
  143.                 httpPostDemo();  
  144.             }  
  145.         });  
  146.           
  147.         Button btn3 = (Button) this.findViewById(R.id.btn3);  
  148.         // DOM - Document Object Model  
  149.         btn3.setText("DOM 解析 XML");  
  150.         btn3.setOnClickListener(new Button.OnClickListener() {  
  151.             public void onClick(View v) {  
  152.                 DOMDemo();  
  153.             }  
  154.         });  
  155.           
  156.         Button btn4 = (Button) this.findViewById(R.id.btn4);  
  157.         // SAX - Simple API for XML  
  158.         btn4.setText("SAX 解析 XML");  
  159.         btn4.setOnClickListener(new Button.OnClickListener() {  
  160.             public void onClick(View v) {  
  161.                 SAXDemo();  
  162.             }  
  163.         });  
  164.     }  
  165.       
  166.     // Android 调用 http 协议的 get 方法  
  167.     // 本例:以 http 协议的 get 方法获取远程页面响应的内容  
  168.     private void httpGetDemo(){  
  169.         try {  
  170.             // 模拟器测试时,请使用外网地址  
  171.             URL url = new URL("http://xxx.xxx.xxx");  
  172.             URLConnection con = url.openConnection();  
  173.               
  174.             String result = "http status code: " + ((HttpURLConnection)con).getResponseCode() + "\n";  
  175.             // HttpURLConnection.HTTP_OK  
  176.               
  177.             InputStream is = con.getInputStream();  
  178.             BufferedInputStream bis = new BufferedInputStream(is);  
  179.             ByteArrayBuffer bab = new ByteArrayBuffer(32);  
  180.             int current = 0;  
  181.             while ( (current = bis.read()) != -1 ){  
  182.                 bab.append((byte)current);  
  183.             }  
  184.             result += EncodingUtils.getString(bab.toByteArray(), HTTP.UTF_8);  
  185.               
  186.             bis.close();  
  187.             is.close();  
  188.   
  189.             textView.setText(result);  
  190.         } catch (Exception e) {  
  191.             textView.setText(e.toString());  
  192.         }  
  193.     }  
  194.       
  195.     // Android 调用 http 协议的 post 方法  
  196.     // 本例:以 http 协议的 post 方法向远程页面传递参数,并获取其响应的内容  
  197.     private void httpPostDemo(){  
  198.         try {  
  199.             // 模拟器测试时,请使用外网地址  
  200.             String url = "http://5billion.com.cn/post.php";  
  201.             Map<String, String> data = new HashMap<String, String>();  
  202.             data.put("name""webabcd");  
  203.             data.put("salary""100");  
  204.               
  205.             DefaultHttpClient httpClient = new DefaultHttpClient();  
  206.             HttpPost httpPost = new HttpPost(url);  
  207.             ArrayList<BasicNameValuePair> postData = new ArrayList<BasicNameValuePair>();  
  208.             for (Map.Entry<String, String> m : data.entrySet()) {  
  209.                 postData.add(new BasicNameValuePair(m.getKey(), m.getValue()));  
  210.             }  
  211.   
  212.             UrlEncodedFormEntity entity = new UrlEncodedFormEntity(postData, HTTP.UTF_8);  
  213.             httpPost.setEntity(entity);  
  214.               
  215.             HttpResponse response = httpClient.execute(httpPost);  
  216.               
  217.             String result = "http status code: " + response.getStatusLine().getStatusCode() + "\n";  
  218.             // HttpURLConnection.HTTP_OK  
  219.               
  220.             HttpEntity httpEntity = response.getEntity();  
  221.               
  222.             InputStream is = httpEntity.getContent();  
  223.             result += convertStreamToString(is);  
  224.               
  225.             textView.setText(result);  
  226.         } catch (Exception e) {  
  227.             textView.setText(e.toString());      
  228.         }  
  229.     }  
  230.       
  231.     // 以 DOM 方式解析 XML(xml 数据详见 res/raw/employee.xml)  
  232.     private void DOMDemo(){  
  233.         try    {  
  234.             DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();  
  235.             DocumentBuilder docBuilder = docFactory.newDocumentBuilder();  
  236.             Document doc = docBuilder.parse(this.getResources().openRawResource(R.raw.employee));  
  237.             Element rootElement = doc.getDocumentElement();  
  238.             NodeList employeeNodeList = rootElement.getElementsByTagName("employee");  
  239.               
  240.             textView.setText("DOMDemo" + "\n");  
  241.             String title = rootElement.getElementsByTagName("title").item(0).getFirstChild().getNodeValue();  
  242.             textView.append(title);  
  243.             for (int i=0; i<employeeNodeList.getLength(); i++){  
  244.                 Element employeeElement = ((Element)employeeNodeList.item(i));  
  245.                 String name = employeeElement.getAttribute("name");  
  246.                 String salary = employeeElement.getElementsByTagName("salary").item(0).getFirstChild().getNodeValue();  
  247.                 String dateOfBirth = employeeElement.getElementsByTagName("dateOfBirth").item(0).getFirstChild().getNodeValue();  
  248.                 textView.append("\nname: "+name+" salary: "+salary+" dateOfBirth: " + dateOfBirth);  
  249.             }  
  250.         } catch (Exception e) {  
  251.             textView.setText(e.toString());      
  252.         }  
  253.     }  
  254.       
  255.     // 以 SAX 方式解析 XML(xml 数据详见 res/raw/employee.xml)  
  256.     // SAX 解析器的实现详见 MySAXHandler.java  
  257.     private void SAXDemo(){  
  258.         try    {  
  259.             SAXParserFactory saxFactory = SAXParserFactory.newInstance();  
  260.             SAXParser parser = saxFactory.newSAXParser();  
  261.             XMLReader reader = parser.getXMLReader();  
  262.               
  263.             MySAXHandler handler = new MySAXHandler();  
  264.             reader.setContentHandler(handler);  
  265.             reader.parse(new InputSource(this.getResources().openRawResource(R.raw.employee)));  
  266.             String result = handler.getResult();  
  267.             textView.setText("SAXDemo" + "\n");  
  268.             textView.append(result);  
  269.         } catch (Exception e) {  
  270.             textView.setText(e.toString());      
  271.         }  
  272.     }  
  273.   
  274.     // 辅助方法,用于把流转换为字符串  
  275.     private String convertStreamToString(InputStream is) {  
  276.         BufferedReader reader = new BufferedReader(new InputStreamReader(is));  
  277.         StringBuilder sb = new StringBuilder();     
  278.   
  279.         String line = null;  
  280.         try {  
  281.             while ((line = reader.readLine()) != null) {  
  282.                 sb.append(line + "\n");  
  283.             }  
  284.         } catch (IOException e) {  
  285.             e.printStackTrace();  
  286.         } finally {  
  287.             try {  
  288.                 is.close();  
  289.             } catch (IOException e) {  
  290.                 e.printStackTrace();  
  291.             }  
  292.         }     
  293.   
  294.         return sb.toString();  
  295.     }  
  296. }  
  297.   
  298.   
  299. 2、用 Handler 来实现异步消息处理,以一个可以实时汇报下载进度的异步下载类为例  
  300. 开发一个 Android 类库,本例中此类库名为 webabcd_util  
  301.   
  302. New -> Java Project  
  303. 项目上点右键 -> Build Path -> Add Libraries -> User Library -> User Libraries -> New -> 为类库起个名字 -> 选中这个类库 -> Add JARs 导入 Android 的 jar 包  
  304. 项目上点右键 -> Build Path -> Add Libraries -> User Library -> 选择 Android 库  
  305.   
  306. DownloadManagerAsync.java  
  307.   
  308. 代码   
  309. package webabcd.util;  
  310.   
  311. import java.io.BufferedReader;  
  312. import java.io.File;  
  313. import java.io.FileOutputStream;  
  314. import java.io.InputStream;  
  315. import java.io.InputStreamReader;  
  316. import java.net.URL;  
  317. import java.net.URLConnection;  
  318.   
  319. import org.apache.http.protocol.HTTP;  
  320.   
  321. import android.os.Handler;  
  322. import android.os.Message;  
  323. import android.util.Log;  
  324.   
  325. // 以一个实例,即异步下载,来演示 Android 的异步消息处理(用 Handler 的方式)  
  326. public class DownloadManagerAsync {  
  327.   
  328.     public DownloadManagerAsync() {  
  329.   
  330.     }  
  331.   
  332.     // 实例化自定义的 Handler  
  333.     EventHandler mHandler = new EventHandler(this);  
  334.   
  335.     // 按指定 url 地址下载文件到指定路径  
  336.     public void download(final String url, final String savePath) {  
  337.         new Thread(new Runnable() {  
  338.             public void run() {  
  339.                 try {  
  340.                     sendMessage(FILE_DOWNLOAD_CONNECT);  
  341.                     URL sourceUrl = new URL(url);  
  342.                     URLConnection conn = sourceUrl.openConnection();  
  343.                     InputStream inputStream = conn.getInputStream();  
  344.   
  345.                     int fileSize = conn.getContentLength();  
  346.   
  347.                     File savefile = new File(savePath);  
  348.                     if (savefile.exists()) {  
  349.                         savefile.delete();  
  350.                     }  
  351.                     savefile.createNewFile();  
  352.   
  353.                     FileOutputStream outputStream = new FileOutputStream(  
  354.                             savePath, true);  
  355.   
  356.                     byte[] buffer = new byte[1024];  
  357.                     int readCount = 0;  
  358.                     int readNum = 0;  
  359.                     int prevPercent = 0;  
  360.                     while (readCount < fileSize && readNum != -1) {  
  361.                         readNum = inputStream.read(buffer);  
  362.                         if (readNum > -1) {  
  363.                             outputStream.write(buffer);  
  364.                             readCount = readCount + readNum;  
  365.   
  366.                             int percent = (int) (readCount * 100 / fileSize);  
  367.                             if (percent > prevPercent) {  
  368.                                 // 发送下载进度信息  
  369.                                 sendMessage(FILE_DOWNLOAD_UPDATE, percent,  
  370.                                         readCount);  
  371.   
  372.                                 prevPercent = percent;  
  373.                             }  
  374.                         }  
  375.                     }  
  376.   
  377.                     outputStream.close();  
  378.                     sendMessage(FILE_DOWNLOAD_COMPLETE, savePath);  
  379.   
  380.                 } catch (Exception e) {  
  381.                     sendMessage(FILE_DOWNLOAD_ERROR, e);  
  382.                     Log.e("MyError", e.toString());  
  383.                 }  
  384.             }  
  385.         }).start();  
  386.     }  
  387.   
  388.     // 读取指定 url 地址的响应内容  
  389.     public void download(final String url) {  
  390.         new Thread(new Runnable() {  
  391.             public void run() {  
  392.                 try {  
  393.                     sendMessage(FILE_DOWNLOAD_CONNECT);  
  394.                     URL sourceUrl = new URL(url);  
  395.                     URLConnection conn = sourceUrl.openConnection();  
  396.                     conn.setConnectTimeout(3000);  
  397.                     BufferedReader reader = new BufferedReader(  
  398.                             new InputStreamReader(conn.getInputStream(),  
  399.                                     HTTP.UTF_8));  
  400.   
  401.                     String line = null;  
  402.                     StringBuffer content = new StringBuffer();  
  403.                     while ((line = reader.readLine()) != null) {  
  404.                         content.append(line);  
  405.                     }  
  406.   
  407.                     reader.close();  
  408.   
  409.                     sendMessage(FILE_DOWNLOAD_COMPLETE, content.toString());  
  410.   
  411.                 } catch (Exception e) {  
  412.                     sendMessage(FILE_DOWNLOAD_ERROR, e);  
  413.                     Log.e("MyError", e.toString());  
  414.                 }  
  415.             }  
  416.         }).start();  
  417.     }  
  418.   
  419.     // 向 Handler 发送消息  
  420.     private void sendMessage(int what, Object obj) {  
  421.         // 构造需要向 Handler 发送的消息  
  422.         Message msg = mHandler.obtainMessage(what, obj);  
  423.         // 发送消息  
  424.         mHandler.sendMessage(msg);  
  425.     }  
  426.   
  427.     private void sendMessage(int what) {  
  428.         Message msg = mHandler.obtainMessage(what);  
  429.         mHandler.sendMessage(msg);  
  430.     }  
  431.   
  432.     private void sendMessage(int what, int arg1, int arg2) {  
  433.         Message msg = mHandler.obtainMessage(what, arg1, arg2);  
  434.         mHandler.sendMessage(msg);  
  435.     }  
  436.   
  437.     private static final int FILE_DOWNLOAD_CONNECT = 0;  
  438.     private static final int FILE_DOWNLOAD_UPDATE = 1;  
  439.     private static final int FILE_DOWNLOAD_COMPLETE = 2;  
  440.     private static final int FILE_DOWNLOAD_ERROR = -1;  
  441.   
  442.     // 自定义的 Handler  
  443.     private class EventHandler extends Handler {  
  444.         private DownloadManagerAsync mManager;  
  445.   
  446.         public EventHandler(DownloadManagerAsync manager) {  
  447.             mManager = manager;  
  448.         }  
  449.   
  450.         // 处理接收到的消息  
  451.         @Override  
  452.         public void handleMessage(Message msg) {  
  453.   
  454.             switch (msg.what) {  
  455.             case FILE_DOWNLOAD_CONNECT:  
  456.                 if (mOnDownloadConnectListener != null)  
  457.                     mOnDownloadConnectListener.onDownloadConnect(mManager);  
  458.                 break;  
  459.             case FILE_DOWNLOAD_UPDATE:  
  460.                 if (mOnDownloadUpdateListener != null)  
  461.                     mOnDownloadUpdateListener.onDownloadUpdate(mManager,  
  462.                             msg.arg1);  
  463.                 break;  
  464.             case FILE_DOWNLOAD_COMPLETE:  
  465.                 if (mOnDownloadCompleteListener != null)  
  466.                     mOnDownloadCompleteListener.onDownloadComplete(mManager,  
  467.                             msg.obj);  
  468.                 break;  
  469.             case FILE_DOWNLOAD_ERROR:  
  470.                 if (mOnDownloadErrorListener != null)  
  471.                     mOnDownloadErrorListener.onDownloadError(mManager,  
  472.                             (Exception) msg.obj);  
  473.                 break;  
  474.             default:  
  475.                 break;  
  476.             }  
  477.         }  
  478.     }  
  479.   
  480.     // 定义连接事件  
  481.     private OnDownloadConnectListener mOnDownloadConnectListener;  
  482.     public interface OnDownloadConnectListener {  
  483.         void onDownloadConnect(DownloadManagerAsync manager);  
  484.     }  
  485.     public void setOnDownloadConnectListener(OnDownloadConnectListener listener) {  
  486.         mOnDownloadConnectListener = listener;  
  487.     }  
  488.   
  489.     // 定义下载进度更新事件  
  490.     private OnDownloadUpdateListener mOnDownloadUpdateListener;  
  491.     public interface OnDownloadUpdateListener {  
  492.         void onDownloadUpdate(DownloadManagerAsync manager, int percent);  
  493.     }  
  494.     public void setOnDownloadUpdateListener(OnDownloadUpdateListener listener) {  
  495.         mOnDownloadUpdateListener = listener;  
  496.     }  
  497.   
  498.     // 定义下载完成事件  
  499.     private OnDownloadCompleteListener mOnDownloadCompleteListener;  
  500.     public interface OnDownloadCompleteListener {  
  501.         void onDownloadComplete(DownloadManagerAsync manager, Object result);  
  502.     }  
  503.     public void setOnDownloadCompleteListener(  
  504.             OnDownloadCompleteListener listener) {  
  505.         mOnDownloadCompleteListener = listener;  
  506.     }  
  507.   
  508.     // 定义下载异常事件  
  509.     private OnDownloadErrorListener mOnDownloadErrorListener;  
  510.     public interface OnDownloadErrorListener {  
  511.         void onDownloadError(DownloadManagerAsync manager, Exception e);  
  512.     }  
  513.     public void setOnDownloadErrorListener(OnDownloadErrorListener listener) {  
  514.         mOnDownloadErrorListener = listener;  
  515.     }  
  516. }  
  517.   
  518.   
  519. 调用上面的自定义的 Android 类库  
  520.   
  521. 项目上点右键 -> Properties -> Java Build Path -> Projects -> Add 引用上面的类库  
  522.   
  523. Main.java  
  524.   
  525. 代码   
  526. package com.webabcd.handler;  
  527.   
  528. import android.app.Activity;  
  529. import android.os.Bundle;  
  530. import android.widget.TextView;  
  531.   
  532. import webabcd.util.DownloadManagerAsync;  
  533.   
  534. public class Main extends Activity implements  
  535.         DownloadManagerAsync.OnDownloadCompleteListener,  
  536.         DownloadManagerAsync.OnDownloadUpdateListener,  
  537.         DownloadManagerAsync.OnDownloadErrorListener {  
  538.       
  539.     TextView txt;  
  540.       
  541.     /** Called when the activity is first created. */  
  542.     @Override  
  543.     public void onCreate(Bundle savedInstanceState) {  
  544.         super.onCreate(savedInstanceState);  
  545.         setContentView(R.layout.main);  
  546.           
  547.         DownloadManagerAsync manager = new DownloadManagerAsync();  
  548.         manager.setOnDownloadCompleteListener(this);  
  549.         manager.setOnDownloadUpdateListener(this);  
  550.         manager.download("http://files.cnblogs.com/webabcd/Android.rar""/sdcard/Android.rar");  
  551.           
  552.         txt = (TextView) this.findViewById(R.id.txt);  
  553.         txt.setText("开始下载");  
  554.     }  
  555.   
  556.     public void onDownloadComplete(DownloadManagerAsync manager, Object result) {  
  557.   
  558.         txt.setText("下载完成");  
  559.     }  
  560.       
  561.     public void onDownloadUpdate(DownloadManagerAsync manager, int percent) {  
  562.   
  563.         txt.setText("下载进度:" + String.valueOf(percent) + "%");  
  564.     }  
  565.       
  566.     public void onDownloadError(DownloadManagerAsync manager, Exception e) {  
  567.   
  568.         txt.setText("下载出错");  
  569.     }  

原创粉丝点击