Android呼叫天氣預報的WebService簡單例子
一、獲取並使用KSOAP包
在Android SDK中並沒有提供呼叫WebService的庫,因此,需要使用第三方的SDK來呼叫WebService。PC版本的WebService庫非常豐富,但這些對Android來說過於龐大。適合手機的WebService客戶端的SDK有一些,比較常用的是KSOAP2。
我下載的最新的是: ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar
注意:
我在使用ksoap2-android時犯了一個低階錯誤:使用時報錯誤:The import org.ksoap2 cannot be resolved。
當時分析這個問題時一直以為是Eclipse出了問題,找了好多方法都不行,
實際是我下載的ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar檔案是錯誤的導致的,走了彎路。
選擇我們的專案,右鍵選單中 Build Path –> Add External Archives… 增加這個下載的包
二,分以下幾步來呼叫 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 = newSoapObject(NAMESPACE, METHOD_NAME);
SoapObject類的第一個引數表示WebService的名稱空間,可以從WSDL文件中找到WebService的名稱空間。
第二個引數表示要呼叫的WebService方法名。
2、設定呼叫方法的引數值,如果沒有引數,可以省略,設定方法的引數值的程式碼如下:
rpc.addProperty("theCityName", "北京");
要注意的是,addProperty方法的第1個引數雖然表示呼叫方法的引數名,但該引數值並不一定與服務端的WebService類中的方法引數名一致,只要設定引數的順序一致即可。
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);
網上有人說這裡的call的第一個引數為null,但是經過我的測試,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、 這時候執行會出錯,提示沒有許可權訪問網路
需要修改 AndroidManifest.xml 檔案,賦予相應許可權
簡單來說就是增加下面這行配置:<uses-permission android:name="android.permission.INTERNET"></uses-permission>
完整的 AndroidManifest.xml 檔案 如下:
注:Android 中在程式碼中為了除錯寫了system.out.print()輸出項
在選單:Window-->show view-->other-->找到Android,選擇Logcat 是可以看到輸出的,
如果你想在一個單獨的視窗看到system.out.print()的輸出的話,可以在logcat介面點那個綠色的“+”好,
在Filter name 和 By log tag裡面均填入System.out,這樣的話你就能在單獨的介面檢視system.out.print()的輸出了!!
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ghj1976.MyWeather" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MyWeatherActivity" 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> <uses-permission android:name="android.permission.INTERNET"></uses-permission> </manifest>
完整的程式碼如下:
package ghj1976.MyWeather; import java.io.UnsupportedEncodingException; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import org.ksoap2.SoapEnvelope; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; //import org.ksoap2.transport.AndroidHttpTransport; import org.ksoap2.transport.HttpTransportSE; public class MyWeatherActivity extends Activity { private Button okButton; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); okButton = (Button) this.findViewById(R.id.btn_Search); okButton.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { String city = "北京"; getWeather(city); } }); } private static final String NAMESPACE = "http://WebXml.com.cn/"; // WebService地址 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; public void getWeather(String cityName) { try { System.out.println("rpc------"); SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME); System.out.println("rpc" + rpc); System.out.println("cityName is " + cityName); rpc.addProperty("theCityName", cityName); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.bodyOut = rpc; envelope.dotNet = true; envelope.setOutputSoapObject(rpc); HttpTransportSE ht = new HttpTransportSE(URL); //AndroidHttpTransport ht = new AndroidHttpTransport(URL); ht.debug = true; ht.call(SOAP_ACTION, envelope); //ht.call(null, envelope); //SoapObject result = (SoapObject)envelope.bodyIn; //detail = (SoapObject) result.getProperty("getWeatherbyCityNameResult"); detail =(SoapObject) envelope.getResponse(); //System.out.println("result" + result); System.out.println("detail" + detail); Toast.makeText(this, detail.toString(), Toast.LENGTH_LONG).show(); parseWeather(detail); return; } catch (Exception e) { e.printStackTrace(); } } private void 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"; System.out.println("weatherToday is " + weatherToday); Toast.makeText(this, weatherToday, Toast.LENGTH_LONG).show(); } }
參考資料