[索引页]
[×××]


系出名门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 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 文档的回调函数
        @Override
         public void endDocument() throws SAXException {
                 // TODO Auto-generated method stub
                 super.endDocument();
        }
        
         // 一发现元素开始标记就回调此函数
        @Override
         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");        
        }

         // 一发现元素结束标记就回调此函数
        @Override
         public void endElement(String uri, String localName, String qName)
                         throws SAXException {
                 if (localName == "title")
                        mIsTitleTag = false;
                 else if (localName == "salary")
                        mIsSalaryTag = false;
                 else if (localName == "dateOfBirth")
                        mIsBirthTag = false;
        }

         // 一发现元素值或属性值就回调此函数
        @Override
         public void characters( char[] ch, int start, int length)
                         throws SAXException {
                 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 package com.webabcd.communication;

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. */
        @Override
         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() {
                         public void onClick(View v) {
                                httpPostDemo();
                        }
                });
                
                Button btn3 = (Button) this.findViewById(R.id.btn3);
                 // DOM - Document Object Model
                btn3.setText( "DOM 解析 XML");
                btn3.setOnClickListener( new Button.OnClickListener() {
                         public void onClick(View v) {
                                DOMDemo();
                        }
                });
                
                Button btn4 = (Button) this.findViewById(R.id.btn4);
                 // SAX - Simple API for XML
                btn4.setText( "SAX 解析 XML");
                btn4.setOnClickListener( new Button.OnClickListener() {
                         public void onClick(View v) {
                                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(){
                try {
                        // 模拟器测试时,请使用外网地址
                        String url = "http://5billion.com.cn/post.php";
                        Map data = new HashMap();
                        data.put("name", "webabcd");
                        data.put("salary", "100");
                        
                        DefaultHttpClient httpClient = new DefaultHttpClient();
                        HttpPost httpPost = new HttpPost(url);
                        ArrayList postData = new ArrayList();
                        for (Map.Entry 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";
                        // HttpURLConnection.HTTP_OK
                        
                        HttpEntity httpEntity = response.getEntity();
                        
                        InputStream is = httpEntity.getContent();
                        result += convertStreamToString(is);
                        
                        textView.setText(result);
                } catch (Exception e) {
                        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                                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);
                        }
                } catch (Exception e) {
                        textView.setText(e.toString());        
                }
        }
        
        // 以 SAX 方式解析 XML(xml 数据详见 res/raw/employee.xml)
        // SAX 解析器的实现详见 MySAXHandler.java
        private void SAXDemo(){
                try        {
                        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);
                } catch (Exception e) {
                        textView.setText(e.toString());        
                }
        }

        // 辅助方法,用于把流转换为字符串
        private String convertStreamToString(InputStream is) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                StringBuilder sb = new StringBuilder();        

                String line = null;
                try {
                        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 -> Java Project
项目上点右键 -> Build Path -> Add Libraries -> User Library -> User Libraries -> New -> 为类库起个名字 -> 选中这个类库 -> Add JARs 导入 Android 的 jar 包
项目上点右键 -> Build Path -> Add Libraries -> User Library -> 选择 Android 库

DownloadManagerAsync.java
package webabcd.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

import org.apache.http.protocol.HTTP;

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 < fileSize && readNum != -1) {
                                                readNum = inputStream.read(buffer);
                                                 if (readNum > -1) {
                                                        outputStream.write(buffer);
                                                        readCount = readCount + readNum;

                                                         int percent = ( int) (readCount * 100 / fileSize);
                                                         if (percent > 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) {
                 new Thread( new Runnable() {
                         public void run() {
                                 try {
                                        sendMessage(FILE_DOWNLOAD_CONNECT);
                                        URL sourceUrl = new URL(url);
                                        URLConnection conn = sourceUrl.openConnection();
                                        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());

                                } catch (Exception e) {
                                        sendMessage(FILE_DOWNLOAD_ERROR, e);
                                        Log.e( "MyError", e.toString());
                                }
                        }
                }).start();
        }

         // 向 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);
                mHandler.sendMessage(msg);
        }

         private void sendMessage( int what, int arg1, int arg2) {
                Message msg = mHandler.obtainMessage(what, arg1, arg2);
                mHandler.sendMessage(msg);
        }

         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);
                                 break;
                         case FILE_DOWNLOAD_COMPLETE:
                                 if (mOnDownloadCompleteListener != null)
                                        mOnDownloadCompleteListener.onDownloadComplete(mManager,
                                                        msg.obj);
                                 break;
                         case FILE_DOWNLOAD_ERROR:
                                 if (mOnDownloadErrorListener != null)
                                        mOnDownloadErrorListener.onDownloadError(mManager,
                                                        (Exception) msg.obj);
                                 break;
                         default:
                                 break;
                        }
                }
        }

         // 定义连接事件
         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 类库

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

Main.java
package com.webabcd.handler;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import webabcd.util.DownloadManagerAsync;

public class Main extends Activity implements
                DownloadManagerAsync.OnDownloadCompleteListener,
                DownloadManagerAsync.OnDownloadUpdateListener,
                DownloadManagerAsync.OnDownloadErrorListener {
        
        TextView txt;
        
         /** Called when the activity is first created. */
        @Override
         public void onCreate(Bundle savedInstanceState) {
                 super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                
                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
[×××]

更多相关文章

  1. Android中Intent的深入解析
  2. Android支持HTML标签
  3. 2019零基础学Android第1课——Android开发环境搭建
  4. Android基础环境搭建及经典的HelloWord
  5. [Android(安卓)Studio系列(五)] Android(安卓)Studio手动配置Gra
  6. Android中解析xml
  7. Android消息机制Looper与VSync的传播
  8. android下载手动下载Android(安卓)SDK
  9. android源码

随机推荐

  1. Android获取在线视频的缩略图方式对比
  2. Android(安卓)SDK的环境变量配置
  3. Simulate android behaviors on win32
  4. android,No Launcher activity found!
  5. Android事件分发机制
  6. Android(安卓)结束进程的方法
  7. android中的震动
  8. Android(安卓)Studio 之 View组件常用属
  9. Error running app: Instant Run require
  10. Android全屏Activity的几种方式