一、獲取並使用KSOAP包
在Android SDK中並沒有提供調用WebService的庫,因此,需要使用第三方的SDK來調用WebService。PC版本的WebService庫非常豐富,但這些對Android來說過於龐大。適合手機的WebService客戶端的SDK有一些,比較常用的是KSOAP2。
KSOAP2 地址:http://code.google.com/p/ksoap2-android/
二、添加SOAP到Android工程
下載後得到SOAP壓縮包將壓縮包解壓將JAR類型文件添加的到安卓工程具體步驟如下圖:
步驟一、
選擇我們的項目,右鍵菜單中 Build Path –> Add External Archives… 增加這個下載的JAR包
增加好後,我們在 選擇我們的項目,右鍵菜單中 Build Path –> Configure Build Path 的 Libraries 中可以看到下面圖我們下載的到的
ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar已經被導入安卓工程。
步驟二、切換到Order and Export 的tab ,選擇在ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar前的checkBox點擊OK。切記不要選擇Android4.x安卓自帶的庫否則運行也會執行出錯,如圖我沒有選擇Android 4,.3(具體原因目前尚未搞懂)
說完了整個環境的搭建,我們在來說說WebService 調用的步驟:
1、指定 WebService 的命名空間和調用方法
import org.ksoap2.serialization.SoapObject;
private static final String NAMESPACE = "http://WebXml.com.cn/";
private static final String METHOD_NAME = "getWeatherbyCityName";
SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME);
SoapObject類的第一個參數表示WebService的命名空間,可以從WSDL文檔中找到WebService的命名空間
第二個參數表示要調用的WebService方法名。
2、設置調用方法的參數值,如果沒有參數,可以省略,設置方法的參數值的代碼如下:
rpc.addProperty("theCityName", "廣州");
3、生成調用Webservice方法的SOAP請求信息。
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.setOutputSoapObject(rpc);
創建SoapSerializationEnvelope對象時需要通過SoapSerializationEnvelope類的構造方法設置SOAP協議的版本號。
該版本號需要根據服務端WebService的版本號設置。
在創建SoapSerializationEnvelope對象後,不要忘了設置SOAPSoapSerializationEnvelope類的bodyOut屬性,
該屬性的值就是在第一步創建的SoapObject對象。
4、創建HttpTransportsSE對象。
這裏不要使用 AndroidHttpTransport ht = new AndroidHttpTransport(URL); 這是一個要過期的類
private static String URL = "http://www.webxml.com.cn/webservices/weatherwebservice.asmx";
HttpTransportSE ht = new HttpTransportSE(URL);
ht.debug = true;
5、使用call方法調用WebService方法
private static String SOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";
ht.call(SOAP_ACTION, envelope);
第一個參數可以爲null,第2個參數就是在第3步創建的SoapSerializationEnvelope對象。
6、獲得WebService方法的返回結果
有兩種方法:
1、使用getResponse方法獲得返回數據。
private SoapObject detail;
detail =(SoapObject) envelope.getResponse();
2、使用 bodyIn 及 getProperty。
private SoapObject detail;
SoapObject result = (SoapObject)envelope.bodyIn;
detail = (SoapObject) result.getProperty("getWeatherbyCityNameResult");
7、訪問webService的主要代碼要寫在子線程中在安卓4.0平臺不允許直接在UI線程也就是Activity的主線程簡歷網絡連接、訪問網絡資源,因爲這些訪問通常是阻塞操作會影響到UI的流暢性這也是安卓4.0平臺以後的一個優化,因此爲了防止出現一些bug我們最好在子線程中進行webService訪問,通過handler將子線程消息返回到主線程中。
8、這時候不要忘記在改 AndroidManifest.xml 文件,添加網絡訪問權限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>否則會執行出錯。
9、這時候你辛辛苦苦寫好所有主程序的時候,不斷地進行調試,不斷地發現Source Not Found這樣的異常程序崩潰,你往往會異常鬱悶和糾結懷疑是不是自己寫的程序不對,懷疑哪裏出現了空引用,是不是環境沒有搭建好,其實可能不是,
只是沒人提醒你在AndroidManifest.xml中要移除對sdk版本的限制,也下面的xml代碼:
<uses-sdk android:minSdkVersion="10"
android:targetSdkVersion="18" />
完整的 AndroidManifest.xml 文件如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.weatherservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.weatherservice.WeatherActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
完整的Java代碼如下:
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import org.ksoap2.*;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import android.widget.*;
public class WeatherActivity extends Activity {
private static final String NAMESPACE = "http://WebXml.com.cn/";
private static String URL = "http://www.webxml.com.cn/webservices/weatherwebservice.asmx";
private static final String METHOD_NAME = "getWeatherbyCityName";
private static String SOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";
private String weatherToday;
private SoapObject detail;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weather);
Button button = (Button)findViewById(R.id.button1);
final Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
if(msg.what==0x123)
Toast.makeText(WeatherActivity.this, msg.obj.toString(), Toast.LENGTH_LONG).show();
}
};
button.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
String city = "廣州";
SoapObject rpc = new SoapObject(NAMESPACE,METHOD_NAME);
rpc.addProperty("theCityName", city);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.setOutputSoapObject(rpc);
HttpTransportSE ht = new HttpTransportSE(URL);
getWeatherThread thread =new getWeatherThread(handler,ht,envelope);
new Thread(thread).start();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.weather, menu);
return true;
}
class getWeatherThread implements Runnable
{
private HttpTransportSE ht;
private Handler handler;
SoapSerializationEnvelope envelope;
public getWeatherThread(Handler handler,HttpTransportSE ht,SoapSerializationEnvelope envelope)
{
this.handler = handler;
this.ht = ht;
this.envelope = envelope;
}
@Override
public void run() {
ht.debug = true;
try {
ht.call(SOAP_ACTION, envelope);
detail =(SoapObject) envelope.getResponse();
System.out.println("detail" + detail);
String weather = parseWeather(detail);
Message msg = new Message();
msg.obj = weather;
msg.what =0x123;
handler.sendMessage(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String parseWeather(SoapObject detail)
throws UnsupportedEncodingException {
String date = detail.getProperty(6).toString();
weatherToday = "今天:" + date.split(" ")[0];
weatherToday = weatherToday + "\n天氣:" + date.split(" ")[1];
weatherToday = weatherToday + "\n氣溫:"
+ detail.getProperty(5).toString();
weatherToday = weatherToday + "\n風力:"
+ detail.getProperty(7).toString() + "\n";
return weatherToday;
}
}
}
Layout.xml省略
本文所參考資料:
http://www.cnblogs.com/ghj1976/archive/2011/04/26/2028904.html
紅色字體部分是本人在實驗過程中遇到的問題,希望大家可以吸取教訓。
本人水平有限希望同行高手發現錯誤不吝賜教,尚未解決的問題可以回答一二謝謝。