Android访问带有对象参数和返回值的.NET Web Service






4.71/5 (6投票s)
用于访问带有对象参数或对象数组的.NET Web Service的类。
引言
最初,我需要开发一个可以调用.NET Web Service(基于SOAP)的Android应用程序。我在网上搜索,发现ksoap2是大多数人推荐的。我的Web Service是一个复杂的Web Service,参数范围从原始类型、日期、对象、对象数组等。所以我尝试先创建一个简单的Web Service,然后尝试使用ksoap2来处理日益复杂的参数。
好的,ksoap2可以很好地调用一个简单的Web Service。但是,我发现我需要下载一个打补丁的ksoap2才能创建一个Object
参数。而且我需要先创建实现KvmSerializable
接口的类。我需要声明带有数字作为参数的getProperty
和setProperty
方法。所以,这对我来说很别扭。不幸的是,我遇到了另一个问题。我的一些参数在.NET Web Service中声明为ByRef
。我如何使用ksoap2获取这些参数?好吧,我没有再次在网上搜索,而是尝试开发自己的类来完成这项工作。
使用代码
假设,你有这个你想调用的.NET Web Service
<webmethod()>
Public Function LoadTargetItemDistrict(periode As DateTime, ByRef detail() _
As ZTA_SFA_TIDD, ByRef errMessage As String) As Boolean
然后你可以使用以下代码从Android调用它
IvanWebService iws = new IvanWebService("http://10.0.2.2:7788/WSSmartLogic/BLScorecard.asmx");
ZTA_SFA_TIDD[] detail = new ZTA_SFA_TIDD[0];
iws.call("LoadTargetItemDistrict", "periode", "2011-03-01", "detail", detail, "errMessage", "");
ZTA_SFA_TIDD[] tidd = new ZTA_SFA_TIDD[1];
Boolean ret = false;
String errMsg = "";
errMsg = (String)iws.getVariableValue("errMessage", new String().getClass());
ret = (Boolean) iws.getReturnValue(ret.getClass());
tidd = (ZTA_SFA_TIDD[])iws.getVariableValue("detail", tidd.getClass());
第一步是使用一个参数创建IvanWebService
对象,该参数指向你的ASMX文件。我使用IP 10.0.2.2从Android模拟器访问我的本地计算机。下一步就是调用你的方法。第一个参数是方法名。其余参数是Web Service参数,以名称、值对的形式呈现。所以我传递了2011年3月作为period,并传递了一个名为detail
的对象数组作为参数。我还传递了一个空字符串作为参数errMessage
。请注意,即使errMessage
在Web Service中声明为ByRef
,我也不需要传递一个变量给errMessage
。
下一步是从调用中获取结果。你使用getReturnValue
来获取Web Service的返回值。你需要将返回值的类作为唯一的参数传递。getReturnValue
方法返回一个Object
,因此你需要将其转换为Boolean
类型。当你想获取ByRef
的值时,只需使用带有两个参数的getVariableValue
。第一个是参数名称,第二个是该参数的类。像往常一样,你需要进行转换。
这就是调用Web Service所需的一切。这比我与ksoap2的旅程简单得多。在忘记之前,这是ZTA_SFA_TIDD
类(目标项目区域详情类)的代码
import java.util.*;
public class ZTA_SFA_TIDD {
public Date Periode;
public String MVGR2;
public String BEZEI;
public String MEINH;
public String ID;
public double Target;
public double Realisasi;
public double PersenRealisasi;
public double Kurang;
public ZTA_SFA_TIDD(){}
}
是的,我知道这个类非常简单,除了一个空构造函数外,不包含任何其他方法。你可以向你的类添加方法,甚至可以将成员变量设为私有,并创建属性方法。
作为说明,我还没有在类代码中解析int
类型。所以如果你需要它,只需更改源代码并添加它。源代码不复杂,添加的位置也很明显。
最后,这是类IvanWebService
的代码
package com.ivan;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class IvanWebService {
private URL mUrl;
private String mResult;
private String mMethodName;
public IvanWebService(String url){
try {
mUrl = new URL(url);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void call(String methodName,Object... args) throws IOException,
IllegalArgumentException, IllegalAccessException{
mMethodName = methodName;
URLConnection conn = mUrl.openConnection();
conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
conn.addRequestProperty("SOAPAction", "http://tempuri.org/" + methodName);
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
String body = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:" +
"xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:" +
"soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<soap:Body>" +
"<" + methodName + " xmlns=\"http://tempuri.org/\">";
body += buildArgs(args);
body += "</" + methodName + ">" +
"</soap:Body>" +
"</soap:Envelope>";
wr.write(body);
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
mResult = "";
String line;
while ((line = rd.readLine()) != null) {
mResult += line;
}
wr.close();
rd.close();
}
private String buildArgs(Object... args)
throws IllegalArgumentException, IllegalAccessException{
String result = "";
String argName = "";
for(int i=0;i<args.length;i++){
if(i % 2 == 0) {
argName = args[i].toString();
}
else{
result += "<" + argName + ">";
result += buildArgValue(args[i]);
result += "</" + argName + ">";
}
}
return result;
}
private String buildArgValue(Object obj)
throws IllegalArgumentException, IllegalAccessException{
Class<?> cl = obj.getClass();
String result = "";
if(cl.isPrimitive()) return obj.toString();
if(cl.getName().contains("java.lang.")) return obj.toString();
if(cl.getName().equals("java.util.Date")){
DateFormat dfm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
return dfm.format((Date)obj);
}
if(cl.isArray())
{
String xmlName = cl.getName().substring(cl.getName().lastIndexOf(".") + 1);
xmlName = xmlName.replace(";", "");
Object[] arr = (Object[])obj;
for(int i=0; i< arr.length; i++)
{
result += "<" + xmlName + ">";
result += buildArgValue(arr[i]);
result += "</" + xmlName + ">";
}
return result;
}
Field[] fields = cl.getDeclaredFields();
for(int i=0;i<fields.length;i++)
{
result += "<" + fields[i].getName() + ">";
result += buildArgValue(fields[i].get(obj));
result += "</" + fields[i].getName() + ">";
}
return result;
}
public String getResult(){
return mResult;
}
public Object getReturnValue(Class<?> cl) throws IllegalAccessException,
InstantiationException, ParseException
{
return getVariableValue(mResult, mMethodName + "Result", cl);
}
public Object getVariableValue(String name, Class<?> cl)
throws IllegalAccessException, InstantiationException, ParseException
{
return getVariableValue(mResult, name, cl);
}
private Object getVariableValue(String body, String name, Class<?> cl)
throws IllegalAccessException, InstantiationException, ParseException
{
int start = body.indexOf("<" + name + ">");
start += name.length() + 2; //with < and > char
int end = body.indexOf("</" + name + ">");
if(end == -1)
body = "";
else
body = body.substring(start, end);
if(cl.getName().toLowerCase().contains("string")) return body;
if(cl.getName().toLowerCase().contains("double")) return Double.parseDouble(body);
if(cl.getName().toLowerCase().contains("date")){
DateFormat dfm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return dfm.parse(body.replace("T"," "));
}
if(cl.getName().toLowerCase().contains("boolean"))
return Boolean.parseBoolean(body);
if(cl.isArray())
{
if(body == "")
return Array.newInstance(cl.getComponentType(), 0); //return empty array
String xmlName = cl.getName().substring(cl.getName().lastIndexOf(".") + 1);
xmlName = xmlName.replace(";", "");
String[] items = body.split("</" + xmlName + ">");
Object arr = Array.newInstance(cl.getComponentType(), items.length);
for(int i=0;i<items.length;i++)
{
items[i] += "</" + xmlName + ">";
Array.set(arr, i, getVariableValue(items[i], xmlName, cl.getComponentType()));
}
return arr;
}
Object result = cl.newInstance();
Field[] fields = cl.getDeclaredFields();
for(int i=0;i<fields.length;i++)
{
fields[i].set(result, getVariableValue(body, fields[i].getName(), fields[i].getType()));
}
return result;
}
}