1. 程式人生 > >在Android 中使用KSOAP2呼叫WebService

在Android 中使用KSOAP2呼叫WebService



WebService 是一種基於SOAP協議的遠端呼叫標準。通過WebService可以將不同作業系統平臺,不同語言、不同技術整合到一起。在Android SDK中並沒有提供呼叫WebService的庫,因此,需要使用第三方類庫(KSOAP2)來呼叫WebService。在本文將介紹在Android 中呼叫WebService的具體細節,並在最後給出一個完整的例子來演示如何使用KSOAP2來呼叫WebService。

安裝第三方類庫:KSOAP2         PC版本的WebService客戶端類庫非常豐富,例如,Axis2、CXF等,但這些類庫對於Android系統過於龐大,也未必很容易移植到 Android系統上。因此,這些開發包並不在我們考慮的範圍內。適合手機的WebService客戶端類庫也有一些。本例使用了比較常用的 KSOAP2。讀者可以從如下的地址下載Android版的KSOAP2。
       將下載後的jar檔案複製到Eclipse工程的lib目錄中(如果沒有該目錄,可以新建一個,當然,也可以放在其他的目錄中)。並在Eclipse工程中引用這個jar包,引用後的Eclipse工程目錄結構如圖1所示。 圖1 引用KSOAP2開發包
使用KSOAP2呼叫WebService        讀者可按如下6步來呼叫WebService的方法。 1. 指定WebService的名稱空間和呼叫的方法名,程式碼如下:
 SoapObject request = new SoapObject("http://service", "getName");  
    SoapObject類的第1個引數表示WebService的名稱空間,可以從WSDL文件中找到WebService的名稱空間。第2個引數表示要呼叫的WebService方法名。 2. 設定呼叫方法的引數值,這一步是可選的,如果方法沒有引數,可以省略這一步。設定方法的引數值的程式碼如下:
    request.addProperty("param1", "value1");  
    request.addProperty("param2", "value2");  
   要注意的是,addProperty方法的第1個引數雖然表示呼叫方法的引數名,但該引數值並不一定與服務端的WebService類中的方法引數名一致,只要設定引數的順序一致即可。 3. 生成呼叫WebService方法的SOAP請求資訊。該資訊由SoapSerializationEnvelope物件描述,程式碼如下:
    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);  
    envelope.bodyOut = request;  
      建立SoapSerializationEnvelope物件時需要通過SoapSerializationEnvelope類的構造方法設定SOAP協 議的版本號。該版本號需要根據服務端WebService的版本號設定。在建立SoapSerializationEnvelope物件後,不要忘了設定 SoapSerializationEnvelope類的bodyOut屬性,該屬性的值就是在第1步建立的SoapObject物件。 4. 建立HttpTransportSE物件。通過HttpTransportSE類的構造方法可以指定WebService的WSDL文件的URL,程式碼如下:
HttpTransportSE ht =   
    new HttpTransportSE("http://192.168.17.156:8080/axis2/services/SearchProductService?wsdl");      
5. 使用call方法呼叫WebService方法,程式碼如下:  
    ht.call(null, envelope);  
call方法的第1個引數一般為null,第2個引數就是在第3步建立的SoapSerializationEnvelope物件。 6. 使用getResponse方法獲得WebService方法的返回結果,程式碼如下:
SoapObject soapObject = (SoapObject) envelope.getResponse();  
示例:通過WebService查詢產品資訊         本例涉及到一個WebService服務端程式和一個OPhone客戶端程式。讀者可直接將服務端程式(axis2目錄)複製到<Tomcat安裝目錄>\webapps目錄中,然後啟動Tomcat,並在瀏覽器位址列中輸入如下的URL: http://localhost:8080/axis2         如果在瀏覽器中顯示如圖2所示的頁面,說明服務端程式已經安裝成功。 surface view2.png 圖2 WebService主頁面         這個服務端WebService程式是SearchProductService,實際上SearchProductService是一個Java類,只 是利用Axis2將其對映成WebService。在該類中有一個getProduct方法。這個方法有一個String型別的引數,表示產品名稱。該方 法返回一個Product物件,該物件有3個屬性:name、price和productNumber。讀者可以使用如下的URL來檢視 SearchProductService的WSDL文件。 http://localhost:8080/axis2/services/SearchProductService?wsdl        顯示WSDL文件的頁面如圖3所示。 surface view3.png 圖3 WSDL文件          在圖3中的黑框中就是WebService的名稱空間,也是SoapObject類的構造方法的第1個引數值。這個WebService程式可以直接使用如下的URL進行測試。 http://localhost:8080/axis2/services/SearchProductService/getProduct?param0=iphone         測試的結果如圖4所示。 surface view4.png 圖4 測試getProduct方法         從圖4所示的測試結果可以看出,Axis2將getProduct方法返回的Product物件直接轉換成了XML文件(實際上是SOAP格式)返回。        下面我們來根據前面介紹的使用KSOAP2的步驟來編寫呼叫WebService的OPhone客戶端程式,程式碼如下:
    package net.blogjava.mobile.wsclient;  
       
    import org.ksoap2.SoapEnvelope;  
    import org.ksoap2.serialization.SoapObject;  
    import org.ksoap2.serialization.SoapSerializationEnvelope;  
    import org.ksoap2.transport.HttpTransportSE;  
    import android.app.Activity;  
    import android.os.Bundle;  
    import android.view.View;  
    import android.view.View.OnClickListener;  
    import android.widget.Button;  
    import android.widget.EditText;  
    import android.widget.TextView;  
       
    public class Main extends Activity implements OnClickListener  
    {  
        @Override  
        public void onClick(View view)  
        {  
            EditText etProductName = (EditText)findViewById(R.id.etProductName);  
            TextView tvResult = (TextView)findViewById(R.id.tvResult);  
            // WSDL文件的URL,192.168.17.156為PC的ID地址  
            String serviceUrl = "http://192.168.17.156:8080/axis2/services/SearchProductService?wsdl";  
            // 定義呼叫的WebService方法名  
            String methodName = "getProduct";  
            // 第1步:建立SoapObject物件,並指定WebService的名稱空間和呼叫的方法名  
            SoapObject request = new SoapObject("http://service", methodName);  
            // 第2步:設定WebService方法的引數  
            request.addProperty("productName", etProductName.getText().toString());  
            // 第3步:建立SoapSerializationEnvelope物件,並指定WebService的版本  
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);  
            // 設定bodyOut屬性  
            envelope.bodyOut = request;  
            // 第4步:建立HttpTransportSE物件,並指定WSDL文件的URL  
            HttpTransportSE ht = new HttpTransportSE(serviceUrl);          
            try  
            {   
                // 第5步:呼叫WebService  
                ht.call(null, envelope);  
                if (envelope.getResponse() != null)  
                {  
                    // 第6步:使用getResponse方法獲得WebService方法的返回結果  
                    SoapObject soapObject = (SoapObject) envelope.getResponse();  
                    // 通過getProperty方法獲得Product物件的屬性值  
                    String result = "產品名稱:" + soapObject.getProperty("name") + "\n";  
                    result += "產品數量:" + soapObject.getProperty("productNumber") + "\n";  
                    result += "產品價格:" + soapObject.getProperty("price");  
                    tvResult.setText(result);  
       
                }  
                else {  
                    tvResult.setText("無此產品.");  
                }  
            }  
            catch (Exception e)  
            {  
            }  
        }  
        @Override  
        public void onCreate(Bundle savedInstanceState)  
        {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main);  
            Button btnSearch = (Button) findViewById(R.id.btnSearch);  
            btnSearch.setOnClickListener(this);  
        }  
    }  
   在編寫上面程式碼時應注意如下兩點:
  • 在 第2步中addProperty方法的第1個引數值是productName,該值雖然是getProduct方法的引數名,但addProperty方 法的第1個引數值並不限於productName,讀者可以將這個引數設為其他的任何字串(但該值必須在XML中是合法的,例如,不是設為 “<”、“>”等XML預留的字串)。
  • 通過SoapObject類的getProperty方法可以獲得Product物件的屬性值,這些屬性名就是圖4所示的測試結果中的屬性名。
        執行本例,在文字框中輸入“htc hero”,單擊【查詢】按鈕,會在按鈕下方顯示如圖5所示的查詢結果。 surface view5.png 圖5  顯示查詢結果 防止UI元件阻塞         從功能上看,本文示例中給出的程式碼並沒有任何問題。但可能有的讀者會有這樣的擔心:如果呼叫WebService的使用者很多,至使服務端響應遲緩;或服務 端的IP根本就不對,那麼在這些情況下,使用者介面的按鈕和文字框元件豈不是象“死”了一樣無法響應使用者的其他動作。當然,發生這種情況的可能性是有的,尤 其是在複雜的網路環境中發生的可能性是很大的,一但發生這種事情,就會使整個軟體系統在使用者體驗上變得非常糟糕。 使用者和開發人員都希望改善這種糟糕的情況。最理想的狀態是單擊按鈕呼叫WebService方法時,即使由於某種原因,WebService方法並未立即返回,介面上的元件仍然會處於活動狀態,也就是說,使用者仍然可以使用當前介面中的其他元件。          在OPhone中可以採用非同步的方式來達到這個目的。非同步實際上就是通過多執行緒的方式來實現。一般使用new Thread(this).start()來建立和開始一個執行緒。但本節並不使用Thread來實現非同步,而是通過AsyncTask類使要執行的任務 (呼叫WebService)在後臺執行。         下面先看看改進後的程式碼。  
    package net.blogjava.mobile.wsclient;  
       
    import org.ksoap2.SoapEnvelope;  
    import org.ksoap2.serialization.SoapObject;  
    import org.ksoap2.serialization.SoapSerializationEnvelope;  
    import org.ksoap2.transport.HttpTransportSE;  
    import android.app.Activity;  
    import android.os.AsyncTask;  
    import android.os.Bundle;  
    import android.view.View;  
    import android.view.View.OnClickListener;  
    import android.widget.Button;  
    import android.widget.EditText;  
    import android.widget.TextView;  
       
    public class Main extends Activity implements OnClickListener  
    {  
        private EditText etProductName;  
        private TextView tvResult;  
       
        class WSAsyncTask extends AsyncTask  
        {  
            String result = "";  
            @Override  
            protected Object doInBackground(Object... params)  
            {  
                try  
                {  
                    String serviceUrl = "http://192.168.17.156:8080/axis2/services/SearchProductService?wsdl";  
                    String methodName = "getProduct";  
                    SoapObject request = new SoapObject("http://service",  
                            methodName);  
                    request.addProperty("productName", etProductName.getText().toString());  
                    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(  
                            SoapEnvelope.VER11);  
                    envelope.bodyOut = request;  
                    HttpTransportSE ht = new HttpTransportSE(serviceUrl);  
       
                    ht.call(null, envelope);  
                    if (envelope.getResponse() != null)  
                    {  
                        SoapObject soapObject = (SoapObject) envelope.getResponse();  
                        result = "產品名稱:" + soapObject.getProperty("name") + "\n";  
                        result += "產品數量:" + soapObject.getProperty("productNumber")  
                                + "\n";  
                        result += "產品價格:" + soapObject.getProperty("price");  
       
                    }  
                    else  
                    {  
                        result = "無此產品.";  
                    }  
                }  
                catch (Exception e)  
                {  
                    result = "呼叫WebService錯誤.";  
                }  
                // 必須使用post方法更新UI元件  
                tvResult.post(new Runnable()  
                {  
                    @Override  
                    public void run()  
                    {  
                        tvResult.setText(result);  
       
                    }  
                });  
                return null;  
            }  
       
        }  
        @Override  
        public void onClick(View view)  
    {  
        // 非同步執行呼叫WebService的任務    
            new WSAsyncTask().execute();  
        }  
        @Override  
        public void onCreate(Bundle savedInstanceState)  
        {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main);  
            Button btnSearch = (Button) findViewById(R.id.btnSearch);  
            btnSearch.setOnClickListener(this);  
            etProductName = (EditText) findViewById(R.id.etProductName);  
            tvResult = (TextView) findViewById(R.id.tvResult);  
       
        }  
    }  
     呼叫WebService的核心程式碼與示例中的程式碼完全一樣,在這裡就不再做具體的介紹了。但在編寫上面的程式碼時還需要注意如下幾點。 1. 一般需要編寫一個AsyncTask的子類來完成後臺執行任務的工作。 2.  AsyncTask的核心方法是doInBackground,當呼叫AsyncTask類的execute方法時,doInBackground方法會非同步執行。因此,可以將執行任務的程式碼寫在doInBackground方法中。 3. 由 於本例中的TextView元件是在主執行緒(UI執行緒)中建立的,因此,在其他的執行緒(doInBackground方法所在的執行緒)中不能直接更新 TextVew元件。為了更新TextView元件,需要使用TextView類的post方法。該方法的引數是一個Runnable物件,需要將更新 TextView元件的程式碼寫在Runnable介面的run方法中。 4. 雖然不能在其他執行緒中更新UI元件,但可以從其他執行緒直接讀取UI元件的值。例如,在doInBackground方法中直接讀取了EditText元件的值。 5. 呼叫AsyncTask類的execute方法後會立即返回。execute方法的引數就是doInBackground方法的引數。doInBackground方法的返回值可以通過AsyncTask.execute(...).get()方法獲得。 讀者可以將本例中的IP改成其他的值,看看單擊按鈕後,是否還可在文字框中輸入其他的內容。如果這個IP是正確的,並且WebService可訪問,那麼會在TextView元件中輸出相應的返回值。 總結        本文主要介紹瞭如何使用KSOAP2來呼叫WebService。KSOAP2是第三方開發的專門用於在移動裝置呼叫WebService的類庫。使用 KSOAP2呼叫WebService可分為6步來完成,其中主要使用了SoapObject物件來指定了要呼叫的方法,然後通過 HttpTransportSE物件的call方法來呼叫WebService的方法,最後通過getResponse方法返回結果。讀者可以通過本文提 供的完整示例來體會使用KSOAP2呼叫WebService的完整過程。在最後還介紹瞭如何通過非同步呼叫WebService的方式來防止因服務端故障 或其他原因導致的UI元件阻塞。

相關推薦

Android 使用KSOAP2呼叫WebService

 WebService 是一種基於SOAP協議的遠端呼叫標準。通過WebService可以將不同作業系統平臺,不同語言、不同技術整合到一起。在Android SDK中並沒有提供呼叫WebService的庫,因此,需要使用第三方類庫(KSOAP2)來呼叫WebServic

android ksoap2 呼叫WebService和WCF服務的區別

如何區分服務是webservice服務和wcf服務 webservice服務網址是以.asmx結尾的,例子:http://ip地址/Interface/MapService.asmx?wsdl wcf服務是以.svc結尾的,例子:http://ip地址/ydyzt/ReadXml

Android 呼叫KSOAP2 呼叫 webservice 報錯:意外的元素,

我用java jax-ws做的webservice,然後用java 通過wsimport生成的client程式碼呼叫webservice正常,但是用android呼叫webservice時,能夠正常返回值,只是傳遞的引數(一個String),伺服器返回的值,顯示接受的st

ksoap2呼叫webservice

使用ksoap2呼叫遠端webservice,程式碼如下: import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; impo

AndroidJava呼叫c++裡面的方法,如何檢視錯誤

向我們如果在Java中呼叫C++裡面的方法,有的時候發現並不執行,也不知道問題卡住哪裡,這個時候在Androidstudio下面會有這樣的一片紅:   ,這個時候就可以通過doc命令列檢視在C++哪一行報錯,: 前面的exe是自己本地NDK目錄下的路徑, -C

AndroidJNI呼叫過程簡述

1.安裝和下載cygwin,下載Android NDK; 2.在ndk專案中JNI介面的設計; 3.使用C/C++實現本地方法; 4.JNI生成動態連結庫.so檔案; 5.將動態連結庫複製到java工程,在Java工程中呼叫,執行Java工程即可。

Android aidl呼叫執行執行緒和同步非同步問題

1,bind服務回撥執行所線上程 客戶端呼叫bindService(intent, mConn, Context.BIND_AUTO_CREATE); ServiceConnection回撥中獲取伺服器端的介面(實現了Binder的類)onService

AndroidJava呼叫C/C++

①  Javah配置,Tool settings填寫的三項在不同平臺是相同的,無需改動。 ②  安裝NDK ,下載安裝包並安裝。 ③  在AS中配置NDK路徑     ④  Make project

androidwebview呼叫撥號盤

webview.setWebViewClient(new WebViewClient(){ public boolean shouldOverrideUrlLoading(WebView view,String url){

delphi 如何呼叫webservice返回dataset 資料集

We're nearly there. Drop a TClientDataset, a TXMLTransformProvider and a TDatasource on the form. Here's what the form looks like now:Link

Android使用Ksoap2呼叫Web service傳遞自定義物件,List,大檔案

JavaBean,List 呼叫 1、匯入Gson.jar包 2、呼叫 new Gson().toJson(obj); new Gson().toJson(list); 將JavaBean或list轉

android使用ksoap2解析webservice的值為anyType{}格式的解決辦法

    遇到的問題,soapObject打印出來的值:GetGongdanResponse{GetGongdanResult=anyType{results=anyType{details=anyType{id=c252cd5d-8e1f-466f-9b1c-95d8ec

關於 ksoap2呼叫 webservice 遇到的一些問題

拿到了 webservice 介面呼叫 不算完整的文件 當用 ksoap2 寫好程式碼 ,去呼叫 webservice 遇到 伺服器返回 500 的錯誤碼 解決方案: 可能是 ksoap2的 jar包有問題, 換一個試試(雖然原來用的這個j

Android 使用KSOAP2調用WebService(轉)

arch 輸出 移植 發包 runnable round csdn service服務 語言   WebService 是一種基於SOAP協議的遠程調用標準。通過WebService可以將不同操作系統平臺,不同語言、不同技術整合到一起。在Android SDK中並沒有提供調

Android通過ksoap2這個框架呼叫webservice大講堂

                        昨天有人問我An

關於androidwebservice使用ksoap2傳遞複雜物件的研究

    android開發中需要與伺服器互動,其中就要用到webservice,google提供了ksoap的外掛,網上很多關於使用字串引數沒有問題,但是如果使用像date,decimal,以及自定義的類物件就不行了,這還要分為兩種情況: 1.date等引數需要new Ma

呼叫webservice 出現的問題

寫完webservice當然要呼叫,但是以前呼叫的都是我們的架構封裝好的方法,我自己也沒有看過,換了一家公司以後,自己又寫了一個介面,這時候隊友跪了,該如何呼叫呢?網上找了許多東西,但真正能用的東西不多,好多沒用的東西還可能會誤導大家,現在寫一下我們自己的構成,可能和你的有很多的不一樣,然後即使不同

android jni開發c++ 呼叫java 方法

    最近幾天搞fbreader 電子書的二次開發,其中需要 c++ 呼叫 java方法解密電子書,所以l老虎吃天,硬著頭皮看c++程式碼。  具體的思路如下,其實也就這幾步:      1. jni 中用到 java反射的方法

Android呼叫攝像頭拍照儲存,並在相簿選擇圖片顯示

我的配置是: android手機版本是7.0 android studio是3.1 android平臺是9.0 我的測試都是在真機上進行的。 首先來看程式碼: package com.example.sunshunli.cameraalbumtest; import a

(轉)Android訪問webservice 糾正網上亂傳的android呼叫Webservice方法。

糾正網上亂傳的android呼叫Webservice方法。   1.寫作背景:   筆者想實現android呼叫webservice,可是網上全是不管對與錯亂轉載的文章,結果不但不能解決問題,只會讓人心煩,所以筆者決定將自己整理好的能用的android呼叫webserv