0
点赞
收藏
分享

微信扫一扫

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

星巢文化 2022-08-23 阅读 16


系出名门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<String, String> data = new HashMap<String, String>();

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

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



DefaultHttpClient httpClient = new DefaultHttpClient();

HttpPost httpPost = 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()));

}


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<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);

}

} 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.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("下载出错");

}

}

举报

相关推荐

0 条评论