Android 中與服務端作 HTTP 通訊

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();
}
}
複製代碼


二、用 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(
" 下載出錯 " ); } }
相關文章
相關標籤/搜索