Android--通过Http协议向web服务器发送XML数据和调用webService
笔记摘要:
这里介绍了向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>