调用Web Service实现天气预报

来源:互联网 发布:天津网络推广 编辑:程序博客网 时间:2024/04/28 16:59

一、概念:Web Service用于消除不同平台、不同语言之间的实现差异,将现有的应用程序发布成开放式服务,从而允许互联网上任何地方、任何平台、任何语言的应用程序来访问该服务。对于Web Service的使用者而言,不管使用何种操作平台、何种编程语言,只要权限允许,都可以调用Web Service,至于Web Service底层是使用什么样的技术实现的对使用者是完全透明的。

二、Web Service特征:

1、自包含性:Web Service是自包含的,Web Service使用者无须安装任何附加软件,只要一种支持Web和XML的编程语言即可;Web Service服务提供者则只需要Web服务器和SOAP服务器。

2、自描述性:Web Service是自描述的,客户端和服务器都无须关心除请求和响应消息的内容和格式之外的任何内容,消息格式与消息内容一起传播,无须外部程序辅助。

2、封装性:Web Service是一种部署在Web应用上的对象,具备良好的封装性。对使用者而言,仅能看到服务描述,而该服务的具体实现、运行平台都是透明的,调用者无须关心,也无法关心。Web Service作为整体提供服务。

3、可编程性:Web Service并不提供图形用户界面,而是提供编程访问的API,Web Service调用者只需知道Web服务器的API接口,即可使用任何平台上的、任何编程语言来调用Web Service。

4、松散耦合:当Web Service的实现发生改变时,调用者无法感受到这种变化。对调用者而言,只要服务实现的接口没有变化,具体实现的改变是完全透明的。

5、高度的平台性:Web Service可以与其他的Web Service进行交互,具有语言和平台无关性,支持CORBA,EJB,DCOM等多种组件标准,支持各种通信协议如:HTTP,SMTP,FTP和RMI等。

6、使用标准协议:Web Service所有的公共协议都使用标准协议描述、传输和交换,这些标准协议在各种平台上完全相同。使用Web Service完全可以在不同供应商之间实现互操作。

7、高度的整合能力:由于Web Service采用简单的、易理解的标准Web协议作为通信协议,完全屏蔽了不同平台的差异,无论CORBA,EJB还是DCOM,都可以通过这种标准的协议进行互操作,实现系统的最高可整合性。

三、优势:

Web Service与其他网络集成技术相比,其优势在于:

1、Web Service使用SOAP作为基本的通信协议,更加简单、易用。

2、Web Service采用已经广泛使用的技术和协议,如XML、HTTP等,因此Web Service更容易掌握。

四、实例:

注:需要引入ksoap2-android-assembly-3.0.0-jar-with-dependencies.jar

下面通过调用http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx站点的提供的Web Service来实现天气预报功能,代码如下:

Activity:

package com.home.activity;import java.util.ArrayList;import java.util.List;import org.ksoap2.serialization.SoapObject;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.AdapterView;import android.widget.AdapterView.OnItemSelectedListener;import android.widget.ArrayAdapter;import android.widget.Spinner;import android.widget.TextView;import android.widget.Toast;import com.home.util.WebServiceUtil;import com.home.weatherforecast.R;public class MyWeatherActivity extends Activity {// 显示省份的列表private Spinner provinceSpinner;// 显示城市的列表private Spinner citySpinner;private TextView todayWeatherText;private TextView tomorrowWeatherText;private TextView afterdayWeatherText;private TextView currentWeatherText;private Handler handler;// 省份集合private List<String> provinces = new ArrayList<String>();// 城市集合private List<String> cities = new ArrayList<String>();private SoapObject detail;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);init();handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if (msg.what == 1) {if (provinces != null) {ArrayAdapter adapter = new ArrayAdapter(MyWeatherActivity.this,android.R.layout.simple_dropdown_item_1line,provinces);// 使用Spinner显示省份列表provinceSpinner.setAdapter(adapter);} else {Toast.makeText(MyWeatherActivity.this, "网络异常",Toast.LENGTH_SHORT).show();}}if (msg.what == 2) {if (cities != null) {ArrayAdapter cityAdapter = new ArrayAdapter(MyWeatherActivity.this,android.R.layout.simple_dropdown_item_1line,cities);// 使用Spinner 显示城市列表citySpinner.setAdapter(cityAdapter);} else {Toast.makeText(MyWeatherActivity.this, "网络异常",Toast.LENGTH_SHORT).show();}}if (msg.what == 3) {String todayWeather = null;String tomorrowWeather = null;String afterdayWeather = null;String currentWeather = null;// 获取天气实况currentWeather = detail.getProperty(4).toString();int index = currentWeather.indexOf(":");// 从实况天气中截取出提示信息String prompt = currentWeather.substring(0, index + 1);// 从实况天气中截取出天气内容String content = currentWeather.substring(index + 1);String newCurrentWeather = prompt + "\n" + content;// 解析今天的天气情况String date = detail.getProperty(7).toString();todayWeather = "今天:" + date.split(" ")[0];todayWeather = todayWeather + "\n天气:" + date.split(" ")[1];todayWeather = todayWeather + "\n气温:"+ detail.getProperty(8).toString();todayWeather = todayWeather + "\n风力:"+ detail.getProperty(9).toString() + "\n";// 解析明天的天气情况date = detail.getProperty(12).toString();tomorrowWeather = "明天:" + date.split(" ")[0];tomorrowWeather = tomorrowWeather + "\n天气:"+ date.split(" ")[1];tomorrowWeather = tomorrowWeather + "\n气温:"+ detail.getProperty(13).toString();tomorrowWeather = tomorrowWeather + "\n风力:"+ detail.getProperty(14).toString() + "\n";// 解析后天的天气情况date = detail.getProperty(17).toString();afterdayWeather = "后天:" + date.split(" ")[0];afterdayWeather = afterdayWeather + "\n天气:"+ date.split(" ")[1];afterdayWeather = afterdayWeather + "\n气温:"+ detail.getProperty(18).toString();afterdayWeather = afterdayWeather + "\n风力:"+ detail.getProperty(19).toString() + "\n";// 更新当天的天气实况currentWeatherText.setText(newCurrentWeather);// 更新今天天气todayWeatherText.setText(todayWeather);// 更新明天天气tomorrowWeatherText.setText(tomorrowWeather);// 更新后天天气afterdayWeatherText.setText(afterdayWeather);}}};new Thread() {public void run() {// 调用远程WebService获取省份列表provinces = WebServiceUtil.getProvinceList();Message msg = new Message();msg.what = 1;handler.sendMessage(msg);}}.start();// 当省份Spinner的选择项改变时provinceSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {@Overridepublic void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {new Thread() {public void run() {// 调用远程WebService根据省份获取城市列表cities = WebServiceUtil.getCityListByProvince(provinceSpinner.getSelectedItem().toString());Message msg = new Message();msg.what = 2;handler.sendMessage(msg);}}.start();}@Overridepublic void onNothingSelected(AdapterView<?> arg0) {}});// 当城市Spinner的选择项被改变时citySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {@Overridepublic void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {// 根据城市获取天气信息showWeather(citySpinner.getSelectedItem().toString());}@Overridepublic void onNothingSelected(AdapterView<?> arg0) {}});}/** * 获取界面组件 */private void init() {todayWeatherText = (TextView) findViewById(R.id.main_tv_weather_today);tomorrowWeatherText = (TextView) findViewById(R.id.main_tv_weather_tomorrow);afterdayWeatherText = (TextView) findViewById(R.id.main_tv_weather_afterday);currentWeatherText = (TextView) findViewById(R.id.main_tv_weather_current);provinceSpinner = (Spinner) findViewById(R.id.main_sp_province);citySpinner = (Spinner) findViewById(R.id.main_sp_city);}/** * 根据城市获取天气信息 *  * @param city *            城市 */private void showWeather(final String city) {new Thread() {public void run() {// 获取远程WebService返回的对象detail = WebServiceUtil.getWeatherByCity(city);Message msg = new Message();msg.what = 3;handler.sendMessage(msg);}}.start();}}

访问WebService的工具类(WebServiceUtil):

package com.home.util;import java.util.ArrayList;import java.util.List;import org.ksoap2.SoapEnvelope;import org.ksoap2.serialization.SoapObject;import org.ksoap2.serialization.SoapSerializationEnvelope;import org.ksoap2.transport.HttpTransportSE;public class WebServiceUtil {// 定义WebService的命名空间static final String SERVICE_NS = "http://WebXml.com.cn/";// 定义WebService提供服务的URLstatic final String SERVICE_URL = "http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx";/** * 调用远程WebService获取省份列表 *  * @return List 省份列表 */public static List<String> getProvinceList() {// 调用的方法String methodName = "getRegionProvince";// 创建HttpTransportSE传输对象HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);ht.debug = true;// 使用SOAP1.1协议创建Envelope对象SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);// 实例化SoapObject对象SoapObject soapObject = new SoapObject(SERVICE_NS, methodName);// 将SoapObject对象设置为SoapSerializationEnvelope对象的传出SOAP消息envelope.bodyOut = soapObject;// 设置与.NET提供的WebService保持较好的兼容性envelope.dotNet = true;try {// 调用WebServiceht.call(SERVICE_NS + methodName, envelope);if (envelope.getResponse() != null) {// 获取服务器响应返回的SOAP消息SoapObject result = (SoapObject) envelope.bodyIn;SoapObject detail = (SoapObject) result.getProperty(methodName+ "Result");// 解析服务器响应的SOAP消息return parseProvinceOrCity(detail);}} catch (Exception e) {e.printStackTrace();}return null;}/** * 根据省份获取城市列表 *  * @param province * @return List 城市列表 */public static List<String> getCityListByProvince(String province) {// 调用的方法String methodName = "getSupportCityString";// 创建HttpTransportSE传输对象HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);ht.debug = true;// 实例化SoapObject对象SoapObject soapObject = new SoapObject(SERVICE_NS, methodName);// 添加一个请求参数soapObject.addProperty("theRegionCode", province);// 使用SOAP1.1协议创建Envelope对象SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);envelope.bodyOut = soapObject;// 设置与.NET提供的WebService保持较好的兼容性envelope.dotNet = true;try {// 调用WebServiceht.call(SERVICE_NS + methodName, envelope);if (envelope.getResponse() != null) {// 获取服务器响应返回的SOAP消息SoapObject result = (SoapObject) envelope.bodyIn;SoapObject detail = (SoapObject) result.getProperty(methodName+ "Result");// 解析服务器响应的SOAP消息return parseProvinceOrCity(detail);}} catch (Exception e) {e.printStackTrace();}return null;}/** * 解析服务器响应的SOAP消息 *  * @param detail *            SOAP消息 * @return List */private static List<String> parseProvinceOrCity(SoapObject detail) {ArrayList<String> result = new ArrayList<String>();for (int i = 0; i < detail.getPropertyCount(); i++) {// 解析出每个省份result.add(detail.getProperty(i).toString().split(",")[0]);}return result;}/** * 根据城市获取天气状况 *  * @param cityName *            城市名称 * @return SoapObject */public static SoapObject getWeatherByCity(String cityName) {String methodName = "getWeather";HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);ht.debug = true;SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);SoapObject soapObject = new SoapObject(SERVICE_NS, methodName);soapObject.addProperty("theCityCode", cityName);envelope.bodyOut = soapObject;// 设置与.NET提供的WebService保持较好的兼容性envelope.dotNet = true;try {ht.call(SERVICE_NS + methodName, envelope);SoapObject result = (SoapObject) envelope.bodyIn;SoapObject detail = (SoapObject) result.getProperty(methodName+ "Result");return detail;} catch (Exception e) {}return null;}}

布局XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="请选择省份:"            android:textSize="20dp" />        <!-- 让用户选择省份的Spinner -->        <Spinner            android:id="@+id/main_sp_province"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="请选择城市:"            android:textSize="20dp" />        <!-- 让用户选择城市的Spinner -->        <Spinner            android:id="@+id/main_sp_city"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </LinearLayout>    <!-- 显示今天天气的文本框 -->    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <TextView            android:id="@+id/main_tv_weather_today"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </LinearLayout>    <!-- 显示明天天气的文本框 -->    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <TextView            android:id="@+id/main_tv_weather_tomorrow"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </LinearLayout>    <!-- 显示后天天气的文本框 -->    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <TextView            android:id="@+id/main_tv_weather_afterday"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </LinearLayout>    <!-- 显示当前天气的文本框 -->    <TextView        android:id="@+id/main_tv_weather_current"        android:layout_width="match_parent"        android:layout_height="wrap_content" /></LinearLayout>

附上图片效果:




 

原创粉丝点击