最近在实习项目中需要用到 Web Service 进行后台网络通讯,期间遇到了不少的问题,现在,项目也差不多做完了,故总结一下。
认识 Web Service
刚开始听说这个项目与后台进行通讯是用 Web Service 的时候,我其实是感到了一些困难,毕竟没用过,只在那本《疯狂 Android 讲义》中看到过,对它的印象就是有一些复杂的协议、可以调用一些“天气接口”,然后就可以看到各种城市的天气状况,总之,就是后台做好了一些东西,你拿来直接展示到客户端。
现在看来,还没有那么简单,于是,我又好好的学习了一下 Web Service,知识点如下:
- Web Service 平台主要涉及的技术有:SOAP(Simple Object Access Protocol, 简单对象访问协议)、WSDL(Web Service Description Language, Web Service 描述语言)、UDDI(Universal Description Discovery and Integration, 通用描述、发现与集成服务)。
- 一条 SOAP 消息就是一份特定的 XML 文档,SOAP 就是规定了 XML 文档该如何写,如:根元素为 “Envelop”,两个子元素为 “Header”(可选)、“Body”(必选)。
- 上面 Body 元素中存放的 SOAP 消息的主体就该按照 WSDL 所规范的格式来写。主要就是访问和使用 Web Service 所必须的信息。
- UDDI 是一种目录服务,通过它,企业可注册并搜索 Web Service。
W3CSchool上也有一些关于 Web Service 的教程,不过,这个教程比较偏向于搭建 Web Service 后台服务给别人用(还有一点比较好奇,为什么他说的“Web Services”加了“s”~~~)
Android 使用 Web Service
一般,Android 应用只是充当 Web Service 的客户端,调用远程 Web Service,会使用到 ksoap2-android 这个 jar 包,操作步骤如下:
(1) 创建 HttpTransportSE 对象,该对象用于调用 Web Service 操作。
(2) 创建 SoapSerializationEnvelope 对象,该对象是 SOAP 消息的载体。
(3) 创建 SoapObject 对象,创建该对象时需要传入所要调用 Web Service 的命名空间、C方法名。
(4) 调用 SoapObject 对象的 addProperty(String name,Object value)方法来设置参数。
(5) 调用 SoapSerializationEnvelope 对象的 setOutputSoapObject() 方法,或者直接对 bodyOut 属性赋值,将 SoapObject 对象设置为 SoapSerializationEnvelope 的传出 SOAP 消息体。
(6) 调用 HttpTransportSE 对象的 call 方法,并以 SoapSerializationEnvelope 作为参数调用远程 Web Service。
(7) 访问 SoapSerializationEnvelope 对象的 bodyIn 属性,返回一个 SoapObject 对象,该对象就代表了 Web Service 的返回消息。
看起来步骤有点多,有点麻烦,其实写一个 Web Service 工具类以后,这一切都变得相当容易。
工具类参考了:Android 通过WebService进行网络编程,使用工具类轻松实现,并进行了适当的调整,以适应于我的项目中来,在此表示十分感谢。
废话不多说,贴上代码(结合上面的步骤一起来看,理解起来效果更佳哟~~)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63public class WebServiceUtil {
private static final String URL = "http://172.16.1.201:18085";
private static final String NAMESPACE = "urn:add";
private static final String METHOD_NAME = "add";
// 含有3个线程的线程池
private static final ExecutorService executorService = Executors
.newFixedThreadPool(3);
public static void callWebService(final ClientData clientData,
final WebServiceCallBack webServiceCallBack) {
// 创建HttpTransportSE对象
final HttpTransportSE httpTransportSE = new HttpTransportSE(URL);
// 创建SoapObject对象并添加参数
SoapObject soapObject = new SoapObject(NAMESPACE, METHOD_NAME);
soapObject.addProperty("ver", clientData.getVer());
soapObject.addProperty("ccmd", clientData.getCcmd());
soapObject.addProperty("skey", clientData.getSkey());
soapObject.addProperty("mac", clientData.getMac());
soapObject.addProperty("x", clientData.getX());
soapObject.addProperty("y", clientData.getY());
soapObject.addProperty("z", clientData.getZ());
// 实例化SoapSerializationEnvelope,传入WebService的SOAP协议的版本号
final SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
// 设置是否调用的是.Net开发的WebService
soapEnvelope.setOutputSoapObject(soapObject);
soapEnvelope.dotNet = true;
httpTransportSE.debug = true;
// 开启线程去访问WebService
executorService.submit(new Runnable() {
@Override
public void run() {
SoapObject resultSoapObject = null;
try {
httpTransportSE.call(NAMESPACE + METHOD_NAME, soapEnvelope);
if (soapEnvelope.getResponse() != null) {
// 获取服务器响应返回的SoapObject
resultSoapObject = (SoapObject) soapEnvelope.bodyIn;
}
} catch (HttpResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} finally {
webServiceCallBack.callBack(resultSoapObject);
}
}
});
}
/**
* 回调接口
*/
public interface WebServiceCallBack {
public void callBack(SoapObject result);
}
}
当然,这个工具类里面的第一个参数 final ClientData clientData 是根据实际项目需要而更改的,主要作用就是为 SoapObject 对象添加参数,另外,别忘了需要添加 ksoap2-android 这个 jar 包。
实际使用时就会很简单,比如下面:1
2
3
4
5
6
7
8
9
10
11
12WebServiceUtil.callWebService(mClientData, new WebServiceCallBack() {
@Override
public void callBack(SoapObject result) {
if (result != null) {
// 获得服务器数据并处理
// handler.sendMessage(···);
} else {
// 无法获得服务器数据
// handler.sendMessage(···);
}
}
});
为了处理网络操作中的异步问题,一个很好的方法就是:通过 handler 将子线程里面的处理结果传给主线程,然后在主线程里更新 UI 就可以了。
实践证明:Web Service 工具类和 handler 一起十分好用!!!
注:图片来自于Dribbble。
————————原创文章,未经许可,请勿转载!!!————————