因为公司需要,所以昨晚上就研究了一下WebService,现在才将文章发出来。
我们在Android开发中,需要掌握的不仅仅是http的请求方式,有时候我们还需要去调用服务器端的Web Services,Web Services到底是什么东西的?怎么来用呢?因为项目需要,所以花了一个晚上的时间研究了一下,下面把学到的给大家分享出来。
一、Web Services在很久之前就有了,所以他并不是一个新鲜的东西。Web Services是建立在通用协议的基础之上,如HTTP、SOAP、UDDI、WSDL等。
Web Services的优势在于提供了异构平台的无缝街接技术手段。由于不同的用户使用不同的硬件平台,不同的操作平台,不同的操作系统,不同的软件,不同的 协议通信,这就产生了互相通信的需求。 Web Service 使任何两个应用程序,只要能读写xml,那么就能互相通信。
Web Service第二个比较大的优势在于可以穿越防火墙,真正的自由通信一般要访问的Web服务器以及要访问的Web Service的客户端很可能位于防火墙后面,都默认关闭其它端口而开发HTTP端口,而Web service 正是基于HTTP的,所以它可以穿越防火墙.
更通俗的理解:通过使用WebService,我们能够像调用本地方法一样去调用远程服务器上的方法。我们并不需要关心远程的那个方法是Java写的,还是PHP或C#写的;我们并不需要关心远程的方法是基于Unix平台,还是Windows平台,也就是说WebService与平台和语言无关。
二、说到了Web Service了,那我们就不得不说其他的两个概念了。
SOAP:SOAP 是基于 XML 的简易协议,是用在分散或分布的环境中交换信息的简单的协议,可使应用程序在 HTTP 之上进行信息交换。或者更简单地说:SOAP 是用于访问网络服务的协议。要进行通信,进行数据访问传输,就必须依赖于一定的协议,而SOAP正是WebService通信中所依赖的一种协议。目前经常使用的SOAP协议有两个版本:SOAP 1.1 和 SOAP 1.2。
WSDL (Web Services Description Language,Web服务描述语言)是一种XML Application,他将Web服务描述定义为一组服务访问点,客户端可以通过这些服务访问点对包含面向文档信息或面向过程调用的服务进行访问(类似远程过程调用)。WSDL首先对访问的操作和访问时使用的请求/响应消息进行抽象描述,然后将其绑定到具体的传输协议和消息格式上以最终定义具体部署的服务访问点。
为了方便我们研究,我们就随便找的一个页面来做例子:
从1可以看出,该WebSerivce所基于的SOAP协议版本是SOAP1.2;
从2可以看出,该WebSerivce的命名空间(NameSpace)是http://WebXml.com.cn;
从3可以看出,该WebService调用的方法名称为:getMobileCodeInfo;
从4可以看出,该WebService调用getMobileCodeInfo方法时需要传入两个参数:mobileCode和userId;
从5可以看出,getMobileCodeInfo方法为返回方法
从6可以看到,调用getMobileCodeInfo方法后,将返回一个名为getMobileCodeInfoResult的结果字符串;
三、下面通过一个例子来展示Android是调用WebService的具体实现
首先你要下载一个WebService的Jar包,这里我提供一个下载地址ksoap2-android.jar下载地址
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
final String result = getRemoteInfo();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,result,Toast.LENGTH_SHORT).show();
}
});
}
}).start();
}
});
点击按钮之后,我们调用了一个getRemoteInfo()的方法,因为这是在同步线程中运行的所以我们需要新建一个线程来执行这个网络耗时操作,否则直接Crash掉。
/**
* 调用WebService的方法
* @return
*/
private String getRemoteInfo() {
// 命名空间
String nameSpace = "http://temp.org/";
// 调用的方法名称
String methodName = "abcCWI_Get";
// EndPoint
String endPoint = "http://1225.555.725.146:62319/sXfJCHJWI/sXJffGCWI.asmx";
// SOAP Action
String soapAction = "http://temp.org/abcCWI_Get";
// 指定WebService的命名空间和调用的方法名
SoapObject rpc = new SoapObject(nameSpace, methodName);
/**
* 设置需调用WebService接口需要传入的两个参数szUserName、szOrderId、szVerifyString
* 如果不需要参数的话,则不写
* 这里不需要参数,所以注释了
*/
//rpc.addProperty("szUserName", "zhangsan");
//rpc.addProperty("szOrderId", "1000000");
//rpc.addProperty("szVerifyString", "ghjhfghjghjhjk");
//生成调用WebService方法的SOAP请求信息,并指定SOAP的版本
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.bodyOut = rpc;
// 设置是否调用的是dotNet开发的WebService
envelope.dotNet = true;
HttpTransportSE transport = new HttpTransportSE(endPoint);
try {
// 调用WebService
transport.call(soapAction, envelope);
} catch (Exception e) {
e.printStackTrace();
}
// 获取返回的数据
SoapObject object = (SoapObject) envelope.bodyIn;
/**
* 获取返回的结果
* IXJCWI_GetVerResult为返回结果键值对的Key值
* szResult才是你需要value值,也就是返回的结果
*/
String szResult = object.getPropertyAsString("IXJCWI_GetVerResult");
return szResult;
}
这里szResult就是服务器给我们返回的结果,是不是很简单呢?其实这里代码写的有些混乱,我们可以将这个方法封装成一个工具类,比如说我们想把得到的结果直接返回到主线程中,用的时候直接调就可以。
下面是封装之后的代码:
/**
* Created by Anonymous-OS on 2016-04-26.
*/
public class WebServiceUtil {
private static SoapObject soapObject;
private static Handler handler = new Handler();
/**
* 调用WebService的方法
*
*/
public static void getWebServiceInfo(String nameSpace, String methodName, final String endPoint, final String s<span style="white-space:pre"> </span>oapAction, final SoapObject soapObject, final OnGetResult onGetResult) {
//开启子线程进行网络的更新
new Thread(new Runnable() {
@Override
public void run() {
//生成调用WebService方法的SOAP请求信息,并指定SOAP的版本
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.bodyOut = soapObject;
// 设置是否调用的是dotNet开发的WebService
envelope.dotNet = true;
HttpTransportSE transport = new HttpTransportSE(endPoint);
try {
// 调用WebService
transport.call(soapAction, envelope);
} catch (Exception e) {
e.printStackTrace();
}
// 获取返回的数据
final SoapObject object = (SoapObject) envelope.bodyIn;
//回调到主线程中进行UI的更新
handler.post(new Runnable() {
@Override
public void run() {
onGetResult.returnCode(object);
}
});
}
}).start();
}
/**
* 回调接口
*/
public interface OnGetResult {
public void returnCode(SoapObject Object);
}
/**
* 单例模式获取到Object的实例
*/
public static SoapObject getObjectInstance(String Space, String method) {
if (soapObject == null) {
synchronized (WebServiceUtil.class) {
if (soapObject == null) {
soapObject = new SoapObject(Space, method);
}
}
}
return soapObject;
}
}
调用方法很简单:
//单例模式获取SoapObject的实例
SoapObject soapObject = WebServiceUtil.getObjectInstance(nameSpace, methodName);
/**
* 下面是请求参数的封装,如果你不需要参数,则直接可以不写
*/
//soapObject.addProperty("szUserName", "zhangsan");
//soapObject.addProperty("szOrderId", "1000000");
//soapObject.addProperty("szVerifyString", "ghjhfghjghjhjk");
WebServiceUtil.getWebServiceInfo(nameSpace, methodName, endPoint, soapAction, soapObject, new WebServiceUtil.OnGetResult() {
@Override
public void returnCode(SoapObject returnObject) {
//注意:这里是UI线程,可以直接更新UI的
String szResult = returnObject.getPropertyAsString("IXJCWI_GetVerResult");
Toast.makeText(MainActivity.this, szResult, Toast.LENGTH_LONG).show();
}
});
总体效果:
源码不提供下载了,因为只要导入jar包了,上面的工具类代码拷过来直接调用就可以,里面的参数要根据自己请求的WebService的地址修改一下,例子很简单,希望能帮助新手朋友。