使用Web Service进行网络编程
Android应用通常都是运行在手机平台上,手机系统的硬件资源是有限的,不管是存储能力还是计算能力都有限,在Android系统上开发、运行一些单用户、小型应用是可能的,
但对于需要进行大量的数据处理、复杂计算的应用,还是只能部署在远程服务器上,Android应用将只是充当这些应用的客户端。
为了让Android应用与远程服务器之间进行交互,可以借助子Java的RMI技术,但这要求远程服务器程序必须采用Java实现;也可以借助于CORBA技术,但这种技术显得过于复杂,除此之外,Web Service是一种不错的选择。
1.Web Service 平台概述
Web Service平台主要涉及的技术有SOAP(Simple Object Access Protocol,简单对象访问协议),WSDL( Web Service Description Language,Web Service描述语言),UDDI(UniversalDescription, Description and Integration,统一描述、发现和整合协议)。
1.1. SOAP (简单对象访问协议)
SOAP (SimpleObject Access Protocol,简单对象访问协议)是一种具有扩展性的;XML消息协议。SOAP允许一个应用程序向另一个应用程序发送XML消息,SOAP消息是从SOAP发送者传至SOAP接收者的单路消息,任何应用程序均可作为发送者或接收者。SOAP仅定义消息结构和消息处理的协议,与底层的传输协议独立。因此,SOAP协议能通过HTTP, JMS 或SMTP协议传输。
SOAP依赖于XML文档来构建,一条SOAP消息就是一份特定的XML文档,SOAP消息包合如下三个主要元素:
Ø必需的
Ø可选的
Ø必需的
1.2. WSDL(WebService描述语言)
WSDL (WebService Description Language, Web Service描述语言)使用 XML描述Web Service,包括访问和使用WebService所必需的信息,定义该Web Service的位置、功能及如何通信等描述信息。
一般来说,只要调用者能够获取WebService对应的WSDL,就可以从中了解它所提供的服务及如何调用Web Service。因为一份WSDL文件淸晰地定义了三个方面的内容。
ØWHAT部分:用于定义Web Service所提供的操作(或方法),也就是Web Service能做些什么。由WSDL中的<types. ../>、<message…/>、和<portTyp…/>元素定义。
ØHOW部分:用于定义如何访问Web Service,包括数据格式详情和访问Web Service操作的必要协议。也就是定义了如何访问Web Service。
ØWHERE部分:用于定义Web Service位于何处,如何使用特定协议决定的网络地址(如URL)指定。该部分使用
一份WSDL文档通常可分为两个部分:
Ø第一个部分定义了服务接口,它在WSDL中由
ØWSDL的第二个部分定义了服务实现,它在WSDL中由
1.3. UDDI(统一描述、发现和整合协议)
UDDI (UniversalDescription, Description and Integration,统一描述、发现和整合协议)是一套信息注册规范,它具有如下特点:
Ø基于Web。
Ø分布式。
UDDI包括一组允许企业向外注册WebService、以使其他企业发现访问的实现标准。 UDDI的核心组件是UDDI注册中心,它使用XML文件来描述企业及其提供的Web Service, 通过使用UDDI, Web Service提供者可以对外注册Web Service,从而允许其他企业来调用该企业注册的Web Service。Web Service提供者通过UDDI注册中心的Web界面,将它所供的Web Service的信息加入UDDI注册中心,该Web Service就可以被发现和调用。
Web Service使用者也通过UDDI注册中心査找、发现自己所需的服务。当Web Service使用者找到自己所需的服务之后,可以将自己绑定到指定的Web Service提供者,再根据该 Web Service对应的WSDL文档来调用对方的服务。
2. 使用Android启用调用Web Service
Java本身提供了丰富的WebService支持,比如Sun公司制定的JAX-WS 2规范,还有 Apache开源组织所提供的Axis1、Axis2、CXF等,这些技术不仅可以用于非常方便地对外提供Web Service,也可以用于简化Web Service的客户端编程。
对于手机等小型设备而言,它们的计算资源、存储资源都十分有限,因此Android应用不大可能需要对外提供Web Service,Android应用通常只是充当Web Service的客户端,调用远程Web Serice。
Google为Android平台开发WebService客户端提供了 ksoap2-android项目,但这个项目并未直接集成在Android平台中,还需要开发人员自行下载。
2.1为Android应用增加ksoap2-android支持的下步骤。
1)登录http://code.google.eom/p/ksoap2-android/站点,该站站点有介绍下载ksoap2-androi项目的方法。
2)下载 ksoap2-android项目的ksoap2-android-assembly-3.0.0-RC4.jar-with-dependencies. jar包。
3)将下载的jar包放到android项目的libs目录下即可。
为Android项目添加了ksoap2-android包之后,接下来借助 ksoap2-android项目来调用WebService所暴露出来的操作。
2.2使用ksoap2-android调用Web Service操作的步驟如下:
1)创建HttpTransportSE对象,该对象用于调用WebService操作。
2)创建 SoapSerializationEnvelope对象。
提示:从名称来看SoapSerializationEnvelope代表一个SOAP消息封包;但ksoap2-android项目对 SoapSerializationEnvelope的处理比较特殊,它是HttpTransportSE调用WebService时信息的载体;客户端需要传入的参数,需要通过SoapSerializationEnvelope对象的bodyOut属性传给服务器;服务器响应生成的SOAP消息也通过该对象的body Out属性来获取。
3)创建SoapObject对象,创建该对象时需要传入所要调用WebService的命名空间、Web Service方法名。
4)如果有参数需要传给Web Service服务器端,调用SoapObject对象的addProperty(Stringname,Object value)方法来设置参数,该方法的name参数指定参数名;value参数指定参数值。
5)调用SoapSerializationEnvelope的setOutputSoapObject()方法,或者直接对bodyOut属性赋值,将前两步创逆的SoapObject对象设为SoapSerializationEnvelope的传出SOAP消息体。
6)调用对象的call()方法,并以SoapSerializationEnvelope作为参数调用远程WebService。
7)调用完成后,访问SoapSerializationEnvelope对象的bodyln属性,该属性返回一个SoapObject对象,该对象就代表了Web Service的返回消息。解析该SoapObject对象,即可获取调用Web Service的返回值。
2.3实例:调用Web Service实现天气预报
在开发天气预报的Android应用之前,首先需要找到一个可以对外提供天气预报的Web Service,通过搜索,发现http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx站点可以对外提供天气预报的WebService,因此程序将会调用该站点的Web Service来实现天气预报。
为了让应用界面更加美观,可以访问http://www.webxml.com.cn/images/weather.zip下载各种天气图标,可以使用这些天气图标来美化应用。
本程序主要需要调用如下三个Web Seivice操作:
获取省份。
根据省份获取城市。
根据城市获取天气。
为了调用上面的三个WebService应用程序提供如下工具类。
publicclass WebServiceUtil { //定义Web Service的命名空间 staticfinal StringSERVICE_NS ="http://WebXml.com.cn/"; //定义Web Service提供服务的URL staticfinal StringSERVICE_URL = "http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx"; //调用远程Web Service获取省份列表 publicstatic 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消息。 returnparseProvinceOrCity(detail); } returnnull; } }); new Thread(task).start(); try { return task.get(); } catch (Exception e) { e.printStackTrace(); } returnnull; } //根据省份获取城市列表 publicstatic 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. |