Android学习--WebService初步

 根据W3C的定义,Web Services(Web服务)是一个用于支持网络间不同机器互操作的软件系统,它是一种自包含、自描述和模块化的应用程序,它可以在网络中被描述、发布和调用,可以将它看作是基于网络的、分布式的模块化组件。

      Web Services是建立在通用协议的基础之上,如HTTP、SOAP、UDDI、WSDL等,这些协议在操作系统、编程语言和对象模型的选择上没有任何倾向,因此有着很强的生命力。

      Web Services的优势在于提供了不同应用程序平台之间的互操作,它使得基于组件的开发和Web相结合的效果达到最佳。它是基于HTTP协议的,调用请求和回应消息都可以穿过防火墙,不需要更改防火墙的设置,这样就避免了使用特殊端口进行通信时无法穿越防火墙的问题。


      简单的理解:通常我们所说的WebService都是远程的某个服务器对外公开了某种服务,或者理解为对外公开了某个功能或者方法,而我们可以通过编程来调用该服务以获得我们需要的信息。例如:www.webxml.com.cn对外公开了手机号码归属地查询服务,我们只需要在调用该服务时传入一个手机号段(号码)就能立即获取该号段的归属地信息。

      更通俗的理解:通过使用WebService,我们能够像调用本地方法一样去调用远程服务器上的方法。我们并不需要关心远程的那个方法是Java写的,还是PHP或C#写的;我们并不需要关心远程的方法是基于Unix平台,还是Windows平台,也就是说WebService与平台和语言无关。


      说到WebSerivce,就必须要知道SOAP和WSDL,它们到底和WebSerice有着怎么的关系?上面已经提到,Web Services是建立在HTTP、SOAP、WSDL等通用协议的基础之上。

      SOAP(Simple Object Access Protocol,简单对象访问协议)是一种轻量级的、简单的、基于XML的协议,被设计用于在分布式环境中交换格式化和固化信息的简单协议。也就是说,要进行通信,进行数据访问传输,就必须依赖于一定的协议,而SOAP正是WebService通信中所依赖的一种协议。目前经常使用的SOAP协议有两个版本:SOAP 1.1 和 SOAP 1.2。

      WSDL(Web Services Description Language,即Web服务描述语言)是一种用来描述Web服务的XML语言,它描述了Web服务的功能、接口、参数、返回值等,便于用户绑定和调用服务。它以一种和具体语言无关的方式定义了给定Web服务调用和应答的相关操作和消息。

    


Android通过调用Webservice实现天气预报

在开发天气预报的Android应用之前,首先需要找到一个可以对外提供天气预报的Web Service,通过搜索发现站点http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx可以对外提供天气预报的Web Service,因此程序会调用此站点的Web Service来实现天气预报。(注意:如果该站点的天气预报Web Service服务已经停止,那么本程序将无法正常调用Web Service,那么天气预报的功能自然也就失效啦)

好啦,现在开始step by step地实现该应用程序。



第一步:获取并使用KSOAP包

在Android SDK中并没有提供调用WebService的库,因此,需要使用第三方的SDK来调用WebService。PC版本的WebService库非常丰富,但这些对Android来说过于庞大。适合手机的WebService客户端的SDK有一些,比较常用的是KSOAP2。

KSOAP2 地址:http://code.google.com/p/ksoap2-android/

我下载的最新的是: ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar


第二步:编写调用Web Service的工具类  ServiceUtil.java

  因为本程序主要需要调用如下三个Web Service操作:

a.获取省份:getRegionProvince方法

b.根据省份获取城市:getSupportCityString方法

c.根据城市获取天气:getWeather方法

  为了让应用界面更加美观,可以访问http://www.webxml.com.cn/images/weather.zip下载各种天气图标,可以使用这些天气图标来美化应用。

package com.example.xiaocool.webservicedemo.Util;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * Created by JustYu on 2015/4/20.
 */
public class ServiceUtil {


    //定义 Web Service 的命名空间
    static final String SERVICE_NS = "http://WebXml.com.cn/";
    //定义Web service 提供服务的URL
    static final String SERVICE_URL = "http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx";

    //调用 Web Service 获取省份列表
    public static List<String> getProvinceList() {
        //调用的方法
        final String methodName = "getRegionProvince";
        //创建HttpTransportSE 传输对象
        final HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
        ht.debug = true;
        //使用SOAP1.1 协议创建Envelop对象
        final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        //实例化 SoapObject对象
        SoapObject soapObject = new SoapObject(SERVICE_NS, methodName);
        envelope.bodyOut = soapObject;
        //设置.Net 提供的web service 保持较好的兼容性
        envelope.dotNet = true;
        FutureTask<List<String>> task = new FutureTask<List<String>>(
                new Callable<List<String>>() {
                    @Override
                    public List<String> call() throws Exception {
                        //调用Web Service
                        ht.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);
                        }
                        return null;
                    }
                }
        );
        new Thread(task).start();
        try {
            return task.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //根据省份获取城市列表
    public static List<String> getCityListByProvince(String province) {
        //调用的方法
        final String methodName = "getSupportCityString";
        //创建HttpTransportSe
        final HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
        ht.debug = true;
        //实例化SoapObject 对象
        SoapObject soapObject = new SoapObject(SERVICE_NS, methodName);
        //添加一个请求参数
        soapObject.addProperty("theRegionCode", province);
        //使用SOAP1.1 协议创建Envelop 对象
        final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.bodyOut = soapObject;
        //设置与。Net 提供的WEB Sertvice  提供较好的兼容性

        envelope.dotNet = true;
        FutureTask<List<String>> task = new FutureTask<List<String>>(
                new Callable<List<String>>() {
                    @Override
                    public List<String> call() throws Exception {
                        //调用Web service
                        ht.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);
                        }
                        return null;
                    }
                }
        );
        new Thread(task).start();
        try {
            return task.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    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;
    }

    public static SoapObject getWeatherByCity(String cityName) {

        final String methodName = "getWeather";
        //创建HttpTransportSE 传输对象
        final HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
        ht.debug = true;
        //使用Soap1.1协议创建 envelop对象
        final 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;
        FutureTask<SoapObject> task = new FutureTask<SoapObject>(
                new Callable<SoapObject>() {
                    @Override
                    public SoapObject call() throws Exception {
                        //调用wenservice              SERVICE_NS+methodName====SoapAction
                        ht.call(SERVICE_NS + methodName, envelope);
                        SoapObject result = (SoapObject) envelope.bodyIn;
                        SoapObject detail = (SoapObject) result.getProperty(methodName + "Result");
                        return detail;
                    }
                });
        new Thread(task).start();
        try {
            return task.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}


第三步:设计应用的UI界面

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <!--省份列表-->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="省份" />

        <Spinner
            android:id="@+id/province"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"></Spinner>
    </LinearLayout>
    <!--城市列表-->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="城市" />

        <Spinner
            android:id="@+id/city"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"></Spinner>
    </LinearLayout>
    <!-- 显示今天天气的图片和文本框-->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/todayWhIcon1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <ImageView
            android:id="@+id/todayWhIcon2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/weatherToday"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>
    <!-- 显示明天天气的图片和文本框-->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/tomorrowWhIcon1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <ImageView
            android:id="@+id/tommorrowWhIcon2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/tommorroToday"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            />

    </LinearLayout>
    <!-- 显示明天天气的图片和文本框-->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/afterdayWhIcon1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <ImageView
            android:id="@+id/afterdayWhIcon2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
        <TextView
            android:id="@+id/afterdayToday"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            />

    </LinearLayout>
    <TextView
        android:id="@+id/weatherCurrent"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

第四步:程序的主应用

package com.example.xiaocool.webservicedemo;


import android.os.Bundle;

import android.support.v7.app.ActionBarActivity;

import android.view.View;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.ImageView;

import android.widget.Spinner;

import android.widget.TextView;


import com.example.xiaocool.webservicedemo.Util.ServiceUtil;


import org.ksoap2.serialization.SoapObject;


import java.util.List;



public class MainActivity extends ActionBarActivity {


    private Spinner provinceSpinner;

    private Spinner citySpinner;

    private ImageView todayWhIcon1;

    private ImageView todayWhIcon2;

    private TextView TextWeatherToday;

    private ImageView tommorrowWhIcon1;

    private ImageView tommorrowWhIcon2;

    private TextView TextWeathertommorrow;

    private ImageView afterdayWhIcon1;

    private ImageView afterdayWhIcon2;

    private TextView TextWeatherafterday;

    private TextView textWeatherCurrent;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        provinceSpinner = (Spinner) this.findViewById(R.id.province);

        citySpinner = (Spinner) this.findViewById(R.id.city);

        todayWhIcon1 = (ImageView) this.findViewById(R.id.todayWhIcon1);

        todayWhIcon2 = (ImageView) this.findViewById(R.id.todayWhIcon2);

        TextWeatherToday = (TextView) this.findViewById(R.id.weatherToday);

        tommorrowWhIcon1 = (ImageView) this.findViewById(R.id.tomorrowWhIcon1);

        tommorrowWhIcon2 = (ImageView) this.findViewById(R.id.tommorrowWhIcon2);

        TextWeathertommorrow = (TextView) this.findViewById(R.id.tommorroToday);

        afterdayWhIcon1 = (ImageView) this.findViewById(R.id.afterdayWhIcon1);

        afterdayWhIcon2 = (ImageView) this.findViewById(R.id.afterdayWhIcon2);

        TextWeatherafterday = (TextView) this.findViewById(R.id.afterdayToday);

        textWeatherCurrent = (TextView) this.findViewById(R.id.weatherCurrent);

        //调用webservice 获取省份

        List<String> provinces = ServiceUtil.getProvinceList();

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, provinces);

        provinceSpinner.setAdapter(adapter);

        //当省份的spinner 的选择项被改变时

        provinceSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

            @Override

            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                List<String> citys=ServiceUtil.getCityListByProvince(provinceSpinner.getSelectedItem().toString());

                ArrayAdapter<String> cityadapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_item, citys);

                citySpinner.setAdapter(cityadapter);

            }


            @Override

            public void onNothingSelected(AdapterView<?> parent) {


            }

        });

        //当城市的Spinner 的选择项被改变是

        citySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

            @Override

            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                ShowWeather(citySpinner.getSelectedItem().toString());

            }


            @Override

            public void onNothingSelected(AdapterView<?> parent) {


            }

        });



    }

  private void ShowWeather(String city){

      String weatherToday=null;

      String weatherTomorrow=null;

      String weatherAfterday=null;

      String weatherCurrent=null;

      int iconToday[]=new int[2];

      int iconTomorrow[]=new int[2];

      int iconAfterday[]=new int[2];

      //获取远程WEB service 返回的对象

      SoapObject detail=ServiceUtil.getWeatherByCity(city);

      //获取天气情况

     // weatherCurrent=detail.getProperty(4).toString();

      //解析今天的天气

      String date=detail.getProperty(7).toString();

      weatherToday="今天:"+date.split(" ")[0];

      weatherToday=weatherToday+"\n天气:"+date.split(" ")[1];

      weatherToday=weatherToday+"\n气温:"+detail.getProperty(8).toString();

      weatherToday=weatherToday+"\n风力:"+detail.getProperty(9).toString()+"\n";

     //更新当天的天气情况

      textWeatherCurrent.setText(weatherCurrent);

      TextWeatherToday.setText(weatherToday);




  }


}

第五步:添加访问网络的权限


注意:如果该站点的天气预报Web Service服务已经停止,那么本程序将无法正常调用Web Service,那么天气预报的功能自然也就失效啦

你可能感兴趣的:(android,webservice,天气预报)