1. 程式人生 > >自己關於Android 通過WebService進行網路程式設計的總結

自己關於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、

Androidwebservice進行實體物件的傳遞

        我是半吊子的安卓開發者,之前沒接觸過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