笔记摘要:
这里介绍了向web服务器提交XML实体数据,通过将请求参数和请求方法按照某种协议封装在XML文件中,提交到WebServices(网络上提供的API,天气查询,股票行情
等服务),webServices通过调用相应的方法,返回某种协议的结果,最终通过客户端对该种协议的数据进行解析,最终将结果显示给用户。这里通过号码归属地查询来演
示该提交方式的用处。
效果图
一、开发前奏
WebServices:看作是发布在网络上的API
思路:
客户端通过xml文件将需要调用的方法和参数封装发送给webService,webSerevice根据信息通过反射调用相应的方法,然后将结果封装成xml文件返回给客户端,
客户端对返回的数据进行解析,最终显示在用户应用的界面
注意:以实体方式发送数据,必须使用POST方式提交,
二、步骤
1、创建一个web服务器,用于提供web服务
2、创建一个业务类,用于处理提交的数据
3、调用手机归属地查询服务的API
登陆http://webservice.webxml.com.cn,进入到手机归属地查询API的页面,可以看到,该API有指定协议soap的数据格式,所以我们要发送相应的soap协议
的数据,所以创建一个soap协议的xml文件soap12.xml用于提交数据
4、对webService返回的数据进行解析
5、设计Android应用页面,输入电话号码,调用业务类返回号码归属地,显示在应用页面
三、代码体现
出现的错误:
请求类型书写的错误,文件名的错误。
在替换占位符时,replace的使用错误,导致每次的结果为:输入的号码错误。应该使用replaceAll方法,
号码归属地API请求方式:soap协议的数据
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<getMobileCodeInfo xmlns="http://WebXml.com.cn/">
<mobileCode>$mobile</mobileCode>
<userID></userID>
</getMobileCodeInfo>
</soap12:Body>
</soap12:Envelope>
号码归属地soap协议返回的数据格式
//webService返回数据格式
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<getMobileCodeInfoResponse xmlns="http://WebXml.com.cn/">
<getMobileCodeInfoResult>string</getMobileCodeInfoResult>
</getMobileCodeInfoResponse>
</soap12:Body>
</soap12:Envelope>
* */
AndroidMainfest.xml文件
<!-- 访问Internet权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
string.xml
<resources>
<string name="app_name">MobileAddressQuery</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_mobile_address_query">MobileAddressQuery</string>
<string name="mobile">手机号</string>
<string name="button">归属地查询</string>
<string name="error">手机归属地查询失败</string>
</resources>
布局文件
<RelativeLayout 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" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
tools:context=".MobileAddressQuery" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/mobile"
android:id="@+id/mobileView"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/mobileText"
android:layout_below="@+id/mobileView"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button"
android:text="@string/button"
android:onClick="query"
android:layout_below="@+id/mobileText"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/address"
android:layout_below="@+id/button"
/>
</RelativeLayout>
号码归属地查询业务类
说明:
读取自定义的soap协议的xml文件,发送请求道webService,获取webService返回的数据,并对于webService返回的数据进行解析
package cn.xushuai.service;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.util.Xml;
import cn.xushuai.util.StreamTool;
/*
* 获取手机号归属地
*
* */
public class AddressService {
public static String getAddress(String mobile) throws Exception{
//读取soap协议的数据,将请求参数和方法传送给webService
String soap = readSoap();
soap = soap.replaceAll("\\$mobile", mobile);//将用户输入的电话号码替换掉原来的占位符
byte[] entity = soap.getBytes();
String path="http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx";//请求路径
HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/soap+xml;charset=UTF-8");//请求类型为soap+xml
conn.setRequestProperty("Content-Length", String.valueOf(entity.length));
conn.getOutputStream().write(entity);//将实体参数写入到内存中,并没有发送给webService
if(conn.getResponseCode()==200){ //判断返回码的同时将请求传送到webService
//对返回结果进行解析
return parseSOAP(conn.getInputStream());
}
return null;
}
//通过pull解析方式对webService返回的数据进行解析
private static String parseSOAP(InputStream xml) throws XmlPullParserException, IOException {
XmlPullParser pullParser = Xml.newPullParser();//获取pull解析器
pullParser.setInput(xml,"UTF-8");//设置输出流和编码格式
int event = pullParser.getEventType();//获取触发事件类型
while(event != pullParser.END_TAG){
switch(event){
case XmlPullParser.START_TAG://触发开始节点事件
if("getMobileCodeInfoResult".equals(pullParser.getName())){//对获取的节点名称进行比较
return pullParser.nextText(); //返回该及点的内容
}
break;
}
event = pullParser.next();//进行下一次遍历
}
return null;
}
/*
* 读取soap协议的请求数据
* */
private static String readSoap() throws Exception {
InputStream inStream = AddressService.class.getClassLoader().getResourceAsStream("soap12.xml");//通过类加载器加载本地本件
byte[] data = StreamTool.read(inStream);
return new String(data);//将读取的字节数据转换成字符数据返回
}
}
用于读取数据的工具类
package cn.xushuai.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/*
读取流中的数据
@return
* */
public class StreamTool {
public static byte[] read(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();//创建一个内存输出流,存放数据
byte[] buf = new byte[1024];
int len = 0;
while((len = inStream.read(buf))!=-1){ //不断读取
outStream.write(buf,0,len);
}
inStream.close();
return outStream.toByteArray();//返回内存中的数据
}
}
添加网络许可
<!-- 访问Internet权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
string.xml
<resources>
<string name="app_name">MobileAddressQuery</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_mobile_address_query">MobileAddressQuery</string>
<string name="mobile">手机号</string>
<string name="button">归属地查询</string>
<string name="error">手机归属地查询失败</string>
</resources>
布局文件
<RelativeLayout 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" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
tools:context=".MobileAddressQuery" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/mobile"
android:id="@+id/mobileView"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/mobileText"
android:layout_below="@+id/mobileView"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button"
android:text="@string/button"
android:onClick="query"
android:layout_below="@+id/mobileText"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/address"
android:layout_below="@+id/button"
/>
</RelativeLayout>