[索引页]
[源码下载]


系出名门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 StringmResult = "" ;

// 打开xml文档的回调函数
@Override
public void startDocument() throws SAXException{
// TODOAuto-generatedmethodstub
super .startDocument();
}

// 关闭xml文档的回调函数
@Override
public void endDocument() throws SAXException{
// TODOAuto-generatedmethodstub
super .endDocument();
}

// 一发现元素开始标记就回调此函数
@Override
public void startElement(Stringuri,StringlocalName,StringqName,
Attributesattributes)
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(Stringuri,StringlocalName,StringqName)
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 StringgetResult(){
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 TextViewtextView;

/** Calledwhentheactivityisfirstcreated. */
@Override
public void onCreate(BundlesavedInstanceState){
super .onCreate(savedInstanceState);
setContentView(R.layout.main);

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

Buttonbtn1
= (Button) this .findViewById(R.id.btn1);
btn1.setText(
" httpgetdemo " );
btn1.setOnClickListener(
new Button.OnClickListener(){
public void onClick(Viewv){
httpGetDemo();
}
});

Buttonbtn2
= (Button) this .findViewById(R.id.btn2);
btn2.setText(
" httppostdemo " );
btn2.setOnClickListener(
new Button.OnClickListener(){
public void onClick(Viewv){
httpPostDemo();
}
});

Buttonbtn3
= (Button) this .findViewById(R.id.btn3);
// DOM-DocumentObjectModel
btn3.setText( " DOM解析XML " );
btn3.setOnClickListener(
new Button.OnClickListener(){
public void onClick(Viewv){
DOMDemo();
}
});

Buttonbtn4
= (Button) this .findViewById(R.id.btn4);
// SAX-SimpleAPIforXML
btn4.setText( " SAX解析XML " );
btn4.setOnClickListener(
new Button.OnClickListener(){
public void onClick(Viewv){
SAXDemo();
}
});
}

// Android调用http协议的get方法
// 本例:以http协议的get方法获取远程页面响应的内容
private void httpGetDemo(){
try {
// 模拟器测试时,请使用外网地址
URLurl = new URL( " http://xxx.xxx.xxx " );
URLConnectioncon
= url.openConnection();

Stringresult
= " httpstatuscode: " + ((HttpURLConnection)con).getResponseCode() + " \n " ;
// HttpURLConnection.HTTP_OK

InputStreamis
= con.getInputStream();
BufferedInputStreambis
= new BufferedInputStream(is);
ByteArrayBufferbab
= 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 (Exceptione){
textView.setText(e.toString());
}
}

// Android调用http协议的post方法
// 本例:以http协议的post方法向远程页面传递参数,并获取其响应的内容
private void httpPostDemo(){
try {
// 模拟器测试时,请使用外网地址
Stringurl = " http://5billion.com.cn/post.php " ;
Map
< String,String > data = new HashMap < String,String > ();
data.put(
" name " , " webabcd " );
data.put(
" salary " , " 100 " );

DefaultHttpClienthttpClient
= new DefaultHttpClient();
HttpPosthttpPost
= new HttpPost(url);
ArrayList
< BasicNameValuePair > postData = new ArrayList < BasicNameValuePair > ();
for (Map.Entry < String,String > m:data.entrySet()){
postData.add(
new BasicNameValuePair(m.getKey(),m.getValue()));
}

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

HttpResponseresponse
= httpClient.execute(httpPost);

Stringresult
= " httpstatuscode: " + response.getStatusLine().getStatusCode() + " \n " ;
// HttpURLConnection.HTTP_OK

HttpEntityhttpEntity
= response.getEntity();

InputStreamis
= httpEntity.getContent();
result
+= convertStreamToString(is);

textView.setText(result);
}
catch (Exceptione){
textView.setText(e.toString());
}
}

// 以DOM方式解析XML(xml数据详见res/raw/employee.xml)
private void DOMDemo(){
try {
DocumentBuilderFactorydocFactory
= DocumentBuilderFactory.newInstance();
DocumentBuilderdocBuilder
= docFactory.newDocumentBuilder();
Documentdoc
= docBuilder.parse( this .getResources().openRawResource(R.raw.employee));
ElementrootElement
= doc.getDocumentElement();
NodeListemployeeNodeList
= rootElement.getElementsByTagName( " employee " );

textView.setText(
" DOMDemo " + " \n " );
Stringtitle
= rootElement.getElementsByTagName( " title " ).item( 0 ).getFirstChild().getNodeValue();
textView.append(title);
for ( int i = 0 ;i < employeeNodeList.getLength();i ++ ){
ElementemployeeElement
= ((Element)employeeNodeList.item(i));
Stringname
= employeeElement.getAttribute( " name " );
Stringsalary
= employeeElement.getElementsByTagName( " salary " ).item( 0 ).getFirstChild().getNodeValue();
StringdateOfBirth
= employeeElement.getElementsByTagName( " dateOfBirth " ).item( 0 ).getFirstChild().getNodeValue();
textView.append(
" \nname: " + name + " salary: " + salary + " dateOfBirth: " + dateOfBirth);
}
}
catch (Exceptione){
textView.setText(e.toString());
}
}

// 以SAX方式解析XML(xml数据详见res/raw/employee.xml)
// SAX解析器的实现详见MySAXHandler.java
private void SAXDemo(){
try {
SAXParserFactorysaxFactory
= SAXParserFactory.newInstance();
SAXParserparser
= saxFactory.newSAXParser();
XMLReaderreader
= parser.getXMLReader();

MySAXHandlerhandler
= new MySAXHandler();
reader.setContentHandler(handler);
reader.parse(
new InputSource( this .getResources().openRawResource(R.raw.employee)));
Stringresult
= handler.getResult();
textView.setText(
" SAXDemo " + " \n " );
textView.append(result);
}
catch (Exceptione){
textView.setText(e.toString());
}
}

// 辅助方法,用于把流转换为字符串
private StringconvertStreamToString(InputStreamis){
BufferedReaderreader
= new BufferedReader( new InputStreamReader(is));
StringBuildersb
= new StringBuilder();

Stringline
= null ;
try {
while ((line = reader.readLine()) != null ){
sb.append(line
+ " \n " );
}
}
catch (IOExceptione){
e.printStackTrace();
}
finally {
try {
is.close();
}
catch (IOExceptione){
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
EventHandlermHandler = new EventHandler( this );

// 按指定url地址下载文件到指定路径
public void download( final Stringurl, final StringsavePath){
new Thread( new Runnable(){
public void run(){
try {
sendMessage(FILE_DOWNLOAD_CONNECT);
URLsourceUrl
= new URL(url);
URLConnectionconn
= sourceUrl.openConnection();
InputStreaminputStream
= conn.getInputStream();

int fileSize = conn.getContentLength();

Filesavefile
= new File(savePath);
if (savefile.exists()){
savefile.delete();
}
savefile.createNewFile();

FileOutputStreamoutputStream
= 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 (Exceptione){
sendMessage(FILE_DOWNLOAD_ERROR,e);
Log.e(
" MyError " ,e.toString());
}
}
}).start();
}

// 读取指定url地址的响应内容
public void download( final Stringurl){
new Thread( new Runnable(){
public void run(){
try {
sendMessage(FILE_DOWNLOAD_CONNECT);
URLsourceUrl
= new URL(url);
URLConnectionconn
= sourceUrl.openConnection();
conn.setConnectTimeout(
3000 );
BufferedReaderreader
= new BufferedReader(
new InputStreamReader(conn.getInputStream(),
HTTP.UTF_8));

Stringline
= null ;
StringBuffercontent
= new StringBuffer();
while ((line = reader.readLine()) != null ){
content.append(line);
}

reader.close();

sendMessage(FILE_DOWNLOAD_COMPLETE,content.toString());

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

// 向Handler发送消息
private void sendMessage( int what,Objectobj){
// 构造需要向Handler发送的消息
Messagemsg = mHandler.obtainMessage(what,obj);
// 发送消息
mHandler.sendMessage(msg);
}

private void sendMessage( int what){
Messagemsg
= mHandler.obtainMessage(what);
mHandler.sendMessage(msg);
}

private void sendMessage( int what, int arg1, int arg2){
Messagemsg
= 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 DownloadManagerAsyncmManager;

public EventHandler(DownloadManagerAsyncmanager){
mManager
= manager;
}

// 处理接收到的消息
@Override
public void handleMessage(Messagemsg){

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 OnDownloadConnectListenermOnDownloadConnectListener;
public interface OnDownloadConnectListener{
void onDownloadConnect(DownloadManagerAsyncmanager);
}
public void setOnDownloadConnectListener(OnDownloadConnectListenerlistener){
mOnDownloadConnectListener
= listener;
}

// 定义下载进度更新事件
private OnDownloadUpdateListenermOnDownloadUpdateListener;
public interface OnDownloadUpdateListener{
void onDownloadUpdate(DownloadManagerAsyncmanager, int percent);
}
public void setOnDownloadUpdateListener(OnDownloadUpdateListenerlistener){
mOnDownloadUpdateListener
= listener;
}

// 定义下载完成事件
private OnDownloadCompleteListenermOnDownloadCompleteListener;
public interface OnDownloadCompleteListener{
void onDownloadComplete(DownloadManagerAsyncmanager,Objectresult);
}
public void setOnDownloadCompleteListener(
OnDownloadCompleteListenerlistener){
mOnDownloadCompleteListener
= listener;
}

// 定义下载异常事件
private OnDownloadErrorListenermOnDownloadErrorListener;
public interface OnDownloadErrorListener{
void onDownloadError(DownloadManagerAsyncmanager,Exceptione);
}
public void setOnDownloadErrorListener(OnDownloadErrorListenerlistener){
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{

TextViewtxt;

/** Calledwhentheactivityisfirstcreated. */
@Override
public void onCreate(BundlesavedInstanceState){
super .onCreate(savedInstanceState);
setContentView(R.layout.main);

DownloadManagerAsyncmanager
= 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(DownloadManagerAsyncmanager,Objectresult){

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

public void onDownloadUpdate(DownloadManagerAsyncmanager, int percent){

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

public void onDownloadError(DownloadManagerAsyncmanager,Exceptione){

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


OK
[源码下载]

更多相关文章

  1. Android消息总线LiveDataBus
  2. Android 数据存储方式
  3. 带着问题学习 Android Handler 消息机制
  4. Android 文件打开方式
  5. Android LinearLayout及TextView的布局方式
  6. Android之快捷方式一——通过应用程序创建快捷方式
  7. Android Studio里面Failed to resolve: 包名 解决方式
  8. Android应用程序创建桌面快捷方式
  9. 【Android】Android 彩信发送的两种方式+源代码

随机推荐

  1. Android(安卓)淡入淡出动画
  2. :开源社区是个好地方:第一个android小程序
  3. [置顶] 一路16有你,一起17前行。Keep不止,A
  4. Android通知管理(NotificationManager)的使
  5. android 情人鸟(情人专属利器)
  6. Android(安卓)内存优化解决方案 (OOM)
  7. Android压缩图片到100K以下并保持不失真
  8. 调试方法之打堆栈加重写控件
  9. Google Nexus 7/Android(安卓)4.1新手入
  10. [转]android 修改ramdisk.img和init.rc &