自己關於Android 通過WebService進行網路程式設計的總結
平時在開發中,都是使用http協議傳送get或post方法,得到一個json的字串,然後解析封裝。
但是今天遇到一個專案,是使用android去呼叫WebService介面來獲取資料,得到的是一個xml的字串並對其進行封裝。這裡就遇到2個問題。
1、android上如何去呼叫一個webService? 網路上關於這裡的資料也比較多,但是要自己真正開發才能瞭解整個流程。這裡我參考了以下幾篇文章
這篇文章從整體流程,介紹瞭如何android上如何呼叫webService,之前不瞭解什麼是webService或者是android開發者剛接觸呼叫webService的同學,都可以看看。
這篇文章最大的亮點是使用了一個自定義的封裝工具類,對呼叫webService進行了很好的封裝,以後呼叫就變得相對簡單了。但是博文提供的一個Demo,最後檢視某個城市具體天氣無法查詢。所以最好還是自己寫一次,加深理解。
以上文章是開發中遇到的一些問題,有需要的同學可以參考下
2、xml的資料解析封裝其實相比json,是複雜不少的,一般常用的是用到pull解析。而且要更具xml內容不同寫不同的解析方法,其實很繁瑣。
接下來整個過程遇到了不少問題,也有不少總結,結合上面的博文和自己理解在這裡寫下來我的一些理解。
首先,android上究竟如何呼叫webService呢,整個流程如下:
1、先使用一個叫ksoap2的jar包,最新的是3.0版,把它放入lib包下即可,點選我下載,注意檢查eclipse中的android private libraries中是否有編譯通過,如有下圖就表示成功。
2、建立HttpTransportsSE物件。通過HttpTransportsSE類的構造方法可以指定WebService的WSDL文件的URL,也就是webService的訪問地址。
HttpTransportSE httpTransportSE = new HttpTransportSE(url);
3、建立SoapObject物件,裡面的引數分別是WebService的名稱空間和呼叫方法名。
SoapObject soapObject = new SoapObject(NAMESPACE, methodName);
4、設定呼叫方法的引數值,如果沒有引數,就不設定,有引數的話呼叫SoapObject物件的addProperty(String name, Object value)方法將引數加入到SoapObject物件中。(注意:設定引數時,引數名不一定需要跟呼叫的伺服器端的引數名相同,只需要對應的順序相同即可)
soapObject.addProperty(“引數名字”, “傳遞的引數值”);
5、例項化SoapSerializationEnvelope,傳入WebService的SOAP協議的版本號。(可以比伺服器的版本更低,但是不能更高。比如最後的VER11為VER12就會出錯。這裡要跟服務端開發的溝通,確定soap的版本號是多少)
SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
6、通過setOutputSoapObject(Object soapObject)將上面第3步建立的SoapObject物件設定到裡面,並設定是否呼叫的是.Net開發的WebService和是否debug等資訊。
soapEnvelope.setOutputSoapObject(soapObject);
soapEnvelope.dotNet = true;
httpTransportSE.debug = true;
7、我們線上程中呼叫HttpTransportsSE物件的call方法就能實現對WebService的呼叫,其中,第一個引數為名稱空間+呼叫方法,第二個引數為第5步建立的SoapSerializationEnvelope物件(因為涉及到網路操作,所以使用了執行緒池來非同步操作呼叫WebService接。)
httpTransportSE.call(NAMESPACE + methodName, soapEnvelope);
8、通過soapEnvelope.bodyIn獲取WebService返回的資訊。返回物件是SoapObject型別,該物件就代表Webservice的返回訊息,析該物件,即可獲得呼叫web service的返回值。
SoapObject
resultSoapObject = (SoapObject) soapEnvelope.bodyIn;
講了這麼多,說說具體怎麼使用,下面的例子用了第2篇部落格的一個工具類
現在我有一個webService,訪問地址是
http://192.168.1.101:8080/webservice/LoginWebservice?wsd
裡面有一個方法getLoginXml,引數的型別是String字串,引數的名字inputXmlString
該方法的功能是,你隨便傳遞一個字串,服務端會列印你字串,並返回下面xml格式的字串
package com.example.webservice;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.http.client.HttpResponseException;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import android.os.Handler;
import android.os.Message;
/**
* 訪問WebService的工具類,使用了執行緒池
*
* @see http://blog.csdn.net/xiaanming
*
* @author xiaanming
*
*/
public class WebServiceUtils {
//下面這個是本機的伺服器地址,使用前需要先部署
//注意,這裡的url地址,如果有?wsdl,必須去掉!!!!比如下面的第2個地址就不行,會出現異常org.xmlpull.v1.XmlPullParserException: expected: START_TAG
public static final String WEB_SERVER_URL = "http://192.168.1.101:8080/webservice/LoginWebservice";
//public static final String WEB_SERVER_URL = "http://192.168.1.101:8080/webservice/LoginWebservice?wsdl";
// 含有3個執行緒的執行緒池
private static final ExecutorService executorService = Executors
.newFixedThreadPool(3);
// 名稱空間 ,注意有的最後帶一個反斜槓,有的沒有,這裡要檢視wsdl文件,具體設定。可以比較如下
//private static final String NAMESPACE = "http://WebXml.com.cn/";、
private static final String NAMESPACE = "http://webservice";
/**
*
* @param url
* WebService伺服器地址
* @param methodName
* WebService的呼叫方法名
* @param properties
* WebService的引數
* @param webServiceCallBack
* 回撥介面,這個回撥介面是自己寫的
*/
public static void callWebService(String url, final String methodName,
HashMap<String, String> properties,
final WebServiceCallBack webServiceCallBack) {
//第1步:先使用一個叫ksoap2的jar包,最新的是3.0版,把它放入lib包下即可
// 第2步 : 建立HttpTransportSE物件,傳遞WebService伺服器地址
final HttpTransportSE httpTransportSE = new HttpTransportSE(url);
// 第3步:建立SoapObject物件
SoapObject soapObject = new SoapObject(NAMESPACE, methodName);
//第4步:如果有引數傳給Web Service伺服器端,呼叫SoapObject物件的addProperty(String name, Object value)方法來設定引數,該方法的name引數指定引數名
// SoapObject新增引數
if (properties != null) {
for (Iterator<Map.Entry<String, String>> it = properties.entrySet()
.iterator(); it.hasNext();) {
Map.Entry<String, String> entry = it.next();
//下面這一句就是給服務端傳遞資料, 分別是引數的名字和 引數的值
//注意:設定引數,引數名不一定需要跟呼叫的伺服器端的引數名相同,只需要對應的順序相同即可!!!!!!!!
soapObject.addProperty(entry.getKey(), entry.getValue());
}
}
// 第5步 :例項化SoapSerializationEnvelope,傳入WebService的SOAP協議的版本號
//可以比伺服器的版本更低,但是不能更高。比如最後的VER11為VER12就會出錯。這裡要跟服務端開發的溝通,確定soap的版本號是多少
final SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
//第6步:將上面的第3步建立的SoapObject物件通過setOutputSoapObject(Object soapObject)設定到裡面,並設定是否呼叫的是.Net開發的WebService和是否debug等資訊
soapEnvelope.setOutputSoapObject(soapObject);
// 設定是否呼叫的是.Net開發的WebService
soapEnvelope.dotNet = true;
httpTransportSE.debug = true;
// 用於子執行緒與主執行緒通訊的Handler
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 將返回值回撥到callBack的引數中
//SoapObject就是服務端返回的引數,需要解析它即可
webServiceCallBack.callBack((SoapObject) msg.obj);
}
};
// 開啟執行緒去訪問WebService
executorService.submit(new Runnable() {
@Override
public void run() {
SoapObject resultSoapObject = null;
try {
//第7步:我們線上程中呼叫HttpTransportsSE物件的call方法就能實現對WebService的呼叫,其中,第一個引數為名稱空間+呼叫方法,第二個引數為第5步建立的SoapSerializationEnvelope物件(因為涉及到網路操作,所以使用了執行緒池來非同步操作呼叫WebService接。)
httpTransportSE.call(NAMESPACE + methodName, soapEnvelope);
if (soapEnvelope.getResponse() != null) {
// 第8步:通過soapEnvelope.bodyIn,獲取伺服器響應返回的SoapObject,該物件就代表Webservice的返回訊息,
//解析該物件,即可獲得呼叫web service的返回值
resultSoapObject = (SoapObject) soapEnvelope.bodyIn;
}
} catch (HttpResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} finally {
// 將獲取的訊息利用Handler傳送到主執行緒
mHandler.sendMessage(mHandler.obtainMessage(0,
resultSoapObject));
}
}
});
}
/**
*
*
* @author xiaanming
*
*/
public interface WebServiceCallBack {
public void callBack(SoapObject result);
}
}
工具類寫好了,那怎麼使用呢
package com.example.webservice;
import java.util.HashMap;
import org.ksoap2.serialization.SoapObject;
import com.example.mydemo.R;
import com.example.webservice.WebServiceUtils.WebServiceCallBack;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
/**
* 通過這個來實現
* @author hemiy
* @copyright
*/
public class TestWebservice extends Activity {
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_webservice);
text=(TextView) findViewById(R.id.content);
}
public void testWeb(View view){
//顯示進度條
ProgressDialogUtils.showProgressDialog(this, "資料載入中...");
//新增引數
HashMap<String, String> properties = new HashMap<String, String>();
//其實這裡的key可以為任意字串,但是不能為數字的字串
// 比如 properties.put("1", "這裡是自己封裝好上傳的xml格式資料");
// 會報異常 java.io.IOException: HTTP request failed, HTTP status: 500
properties.put("h", "這裡是自己封裝好上傳的xml格式字串資料");
WebServiceUtils.callWebService(WebServiceUtils.WEB_SERVER_URL, "getLoginXml", properties, new WebServiceCallBack() {
//呼叫返回的資料執行如下的程式碼
public void callBack(SoapObject result) {
ProgressDialogUtils.dismissProgressDialog();
if(result != null){
String name = result.getProperty(0).toString();
text.setText(name);
}else{
Toast.makeText(TestWebservice.this, "獲取資料錯誤", Toast.LENGTH_SHORT).show();
}
}
});
}
}
tomcat伺服器的列印結果,表示成功。
開發中遇到問題
1、android連線webservice報java.io.Exception: Http request failed,Http status 500 tran.call出錯。
http 500錯誤是伺服器內部錯誤,確認你是否安裝介面指定引數格式提交或者與伺服器端溝通確認。
2、注意名稱空間是否帶下劃線;
3、注意傳遞的引數“名字”是否正確,有的服務端要求名字一定要指定的,如天氣預報。而自己的伺服器除了數字字串,其實可以任意取名
4、這裡的伺服器url地址,如果有?wsdl,必須去掉!!!!
比如下面的地址就不行,會出現異常org.xmlpull.v1.XmlPullParserException: expected: START_TAG
public static final String WEB_SERVER_URL = "http://192.168.1.101:8080/webservice/LoginWebservice?wsdl";
5、一些參考的網址(12月7日更新)
這個是一個常見的報錯,原因是伺服器回傳的不是xml,不能用ksoap2必須使用http傳送post請求
以上是一些錯誤異常分析
以上是如何使用http去呼叫服務端的例子
以上是檢視的文章
常用的webservice服務
相關推薦
自己關於Android 通過WebService進行網路程式設計的總結
平時在開發中,都是使用http協議傳送get或post方法,得到一個json的字串,然後解析封裝。 但是今天遇到一個專案,是使用android去呼叫WebService介面來獲取資料,得到的是一個xml的字串並對其進行封裝。這裡就遇
Android 通過WebService進行網路程式設計,使用工具類輕鬆實現
相信大家在平常的開發中,對網路的操作用到HTTP協議比較多,通過我們使用Get或者Post的方法呼叫一個數據介面,然後伺服器給我們返回JSON格式的資料,我們解析JSON資料然後展現給使用者,相信很多人很喜歡伺服器給我們返回JSON資料格式,因為他解析方便,也有一些JSON的
Java 計算機網路(網路程式設計總結)
本文主要是自己在網路程式設計方面的學習總結,先主要介紹計算機網路方面的相關內容,包括計算機網路基礎,OSI參考模型,TCP/IP協議簇,常見的網路協議等等,在此基礎上,介紹Java中的網路程式設計。 一、概述 計算機網路是通過傳輸介質、通訊設施和網路通訊協議,把
linux網路程式設計總結(1)
網路程式設計就是通過網路協議實現計算機間的通訊。那麼就有兩個問題,如何精準的定位主機和如何進行高效的資料傳輸。 IP地址來標識網路中的主機,埠號用來定位主機中的某個程序。通過IP和埠號可以唯一確定網路的某臺計算機中的程序。 套接字 即socket,用於描述IP地址和埠,
Socket網路程式設計總結
網路中程序之間如何通訊 Java最初是作為網路程式語言出現的,其對網路提供了高度的支援,使得客戶端和伺服器的溝通變成了現實,而在網路程式設計中,使用最多的就是Socket。像大家熟悉的QQ、MSN都使用了Socket相關的技術。 1.網路的基礎知識 1)
網路程式設計總結
一:確認網路環境3G/WIFI 1. 新增源檔案和framework 開發Web等網路應用程式的時候,需要確認網路環境,連線情況等資訊。如果沒有處理它們,是不會通過Apple的審(我們的)查的。 Apple 的 例程 Reachability 中介紹了取得/檢測網路
_052_Android_Android網路程式設計總結
1.httpURLConnection協議使用 1)建立一個URL物件 2)利用HttpURLConnection物件從網路中獲取網頁資料,設定請求方法 HttpURLConnection conn = (HttpURLConnection) url.openC
Android通過URL獲取網路資料
本例項主要是通過URL獲取網路資源,在具體一點,就是簡單介紹如何獲取網頁文字資源。獲取網路資源還有獲取圖片、視訊、音訊……資源,框架基本相似。 實驗時出現兩點小問題:1、丟擲Connection Refused的異常;
python中網路程式設計總結(udp,tcp)
一、udp使用者資料報協議(寫信的模型:在通訊開始,不需要建立相關的連線,只需要傳送資料即可,類似於生活中的寫信)(不安全:發的訊息可能會丟,對方不會請求再發一遍) 1.ipv4:_ _ _ ._ _ _ . _ _ _ ._ _ _ 192.168.1.1 注:192.168 是代表的同一
Android利用Fiddler進行網路資料抓包
主要介紹Android及IPhone手機上如何利用Fiddler進行網路資料抓包,比如我們想抓某個應用(微博、微信、墨跡天氣)的網路通訊請求就可以利用這個方法。 Mac 下請使用 Charles 代替 Fiddler,Charles 免費啟用碼為Registered
android開發筆記之網路程式設計—簡易新聞客戶端
今天我們來對前面講過的知識綜合運用一下,包括xml的PULL解析,listView的萬能介面卡等知識。。。。 那先來看一個元件—->智慧圖片載入器(smart-image-view),它可以很方便的載入一張網路圖片。 SmartImageView的設計
Tilera多執行緒網路程式設計總結
http://blog.csdn.net/zwleagle/article/details/8851400 http://blog.sina.com.cn/s/blog_a574f78401015v2o.html http://www.dssz.com/13413
高效能網路程式設計總結及《TCP/IP Sockets程式設計(C語言實現) (第2版)》 程式碼下載(連結以及檔案打包)
這篇文章將試圖說明應用程式如何接收網路上傳送過來的TCP訊息流,由於篇幅所限,暫時忽略ACK報文的回覆和接收視窗的滑動。 為了快速掌握本文所要表達的思想,我們可以帶著以下問題閱讀: 1、應用程式呼叫read、recv等方法時,socket套接字可以設定為阻塞或者非阻塞,這兩種方式是如何工作的? 2、
Android與webservice進行實體物件的傳遞
我是半吊子的安卓開發者,之前沒接觸過java的網站開發。因此在開發android應用程式中,首選工具就是VS2010+Eclipse。那麼android開發中與伺服器的通訊也理所當然的使用webservice。 android程式與伺服器端的
Android使用Retrofit進行網路請求
Retrofit 簡介 用於Android和Java平臺的一款型別安全的HTTP客戶端,通過一個Java介面實現HTTP請求物件,如下: public interface Github { @GET("/repos/{owner}/{repo}/
黑馬程式設計師——JavaSE之網路程式設計總結一
網路模型 OSI(Open System Interconnection開放系統互連)參考模型 TCP/IP參考模型 網路通訊要素 IP地址 埠號 傳輸協議 OSI七層
Android okhttp3來進行網路資料請求和傳送
在開發過程中我們很多地方都要和伺服器進行互動以及請求資料,本篇部落格簡單的介紹下okhttp3。 1.get請求 2.post請求 3.上傳檔案 4.下載檔案 ok,下面我們就要準備下如何封裝使用okhttp3。 在Android studio中我們可以在app---
Android程式中,內嵌ELF可執行檔案-- Android開發C語言混合程式設計總結
前言 都知道的,Android基於Linux系統,然後覆蓋了一層由Java虛擬機器為核心的殼系統。跟一般常見的Linux+Java系統不同的,是其中有對硬體驅動進行支援,以避開GPL開源協議限制的HAL硬體抽象層。 大多數時候,我們使用JVM語言進行程式設計,比如傳統的Java或者新貴Kotlin。碰到對
網路程式設計 總結
目錄 1.C/S B/S架構 2.網路通訊原理 3.osi七層協議 4.UDP TCP 協議 5.TCP協議的三次握手和四次揮手 6.socket套接字 7.基
Android網路程式設計網上文章總結
關於網路程式設計,網上也有許多好的文章,這裡我就選了幾篇覺得不錯的歸納到了一起,僅供參考 首先,應該瞭解的幾個問題: 1)Android平臺網路相關API介面 a) java.net.*(標準Java介面) java.net.*提供與聯網有關的類,包括流、資料包套接字(socket)、Inter