Using ksoap2 for android, and parsing output data
So the other day, I was asked to check out how we could use soap on Android, preferably with ksoap2 for android, and a public SOAP Web Service. For the latter the TopGoalScorers web service was chosen.
This example will prepare a soap message with one extra variable and value (iTopN, 5) and get a soap object as response.
- private static final String SOAP_ACTION = "http://footballpool.data
access.eu/data/TopGoalScorers& quot;; - //you can get these values from the wsdl file^
- SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); //set up request
- request.addProperty("iTopN", "5"); //variable name, value. I got the variable name, from the wsdl file!
- SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); //put all required data into a soap envelope
- envelope.setOutputSoapObject(request); //prepare request
- httpTransport.debug = true; //this is optional, use it if you don't want to use a packet sniffer to check what the sent message was (httpTransport.requestDump)
- httpTransport.call(SOAP_ACTION, envelope); //send request
- SoapObject result=(SoapObject)envelope.getResponse(); //get response
- return result;
- }
- //usage:
- //SoapObject result=soap(METHOD_NAME, SOAP_ACTION, NAMESPACE, URL);
- //don't forget to catch the exceptions!!
So after I managed to get a proper soap response, it was time to parse it. I couldn't find any proper already made method to parse it, that actually worked.
You can get the soap objects elements, line by line like this...
- result.getProperty(elementNumber).toString();
...but, this is it! There is no getValue(), or anything like it that would even resemble a parser.
A response soap message from ksoap2 looks like this:
- anyType{tTopGoalScorer=anyType{sName=Gonzalo HiguaÃn; iGoals=3; sCountry=Y; sFlag=http://footballpool.dataaccess.eu/i
mages/flags/ar.gif; }; tTopGoalScorer=anyType{sName=A samoah Gyan; iGoals=2; sCountry=Y; sFlag=http://footballpool.data access.eu/images/flags/gh.gif; }; tTopGoalScorer=anyType{sName=B rett Holman; iGoals=2; sCountry=Y; sFlag=http://footballpool.data access.eu/images/flags/au.gif; }; tTopGoalScorer=anyType{sName=C hung-Yong Lee; iGoals=2; sCountry=Y; sFlag=http://footballpool.data access.eu/images/flags/kr.gif; }; tTopGoalScorer=anyType{sName=D avid Villa; iGoals=2; sCountry=Y; sFlag=http://footballpool.data access.eu/images/flags/es.gif; }; }
Pretty well structured, but a pain in the ass to work with.
The official documentation suggests a way to implement and register an object with the Marshal interface, but after seeing the string representation above, it seems to be way too complicated. Let's see how we could make things easier, and more importantly, let's try to achieve it in a generalized way.
This is one element:
- {sName=Gonzalo HiguaÃn; iGoals=3; sCountry=Y; sFlag=http://footballpool.dataaccess.eu/i
mages/flags/ar.gif; }
Obviously I could make something like this fast, but this is only works for the example service.
- //parse the soap object, one element at a time.
- String sName=input.substring(input.indexOf("sName=")+6, input.indexOf(";", input.indexOf("sName=")));
- int IGoals=Integer.valueOf(input.substring(input.indexOf("iGoals=")+7, input.indexOf(";", input.indexOf("iGoals="))));
- String sCountry=input.substring(input.indexOf("sCountry=")+9, input.indexOf(";", input.indexOf("sCountry=")));
- String sFlag=input.substring(input.indexOf("sFlag=")+6, input.indexOf(";", input.indexOf("sFlag=")));
- }
..but doing this every time, for every response message type, is just multiplying code, and too much work anyway.
After wondering a couple of minutes over the code, it looked as we could create a general method with reflection to do the job.
The method above receives one line of string from the result object, and a class, that has public members. To be able to map the SOAP response values with the corresponding members, the names and types of the member fields have to be exactly the same, as they are in the result response. As in the first example, we used the TopGoalScorers method, to test the parser, it had the following fields: sName, iGoals, sCountry, sFlag. For our web service example the result class (aka Business Object) is:
And here comes the parser implementation. Please note, that in the current form this only works with primitive types, like String, int, Integer, float and Float.
- package com.helloandroid.ksoap2;
- import java.lang.reflect.Field;
- import java.lang.reflect.Type;
- /**
- * Ksoap2 for android - output parser
- * This class parses an input soap message
- * @author tamas.beres@helloandroid com, akos.birtha@helloandroid com
- *
- */
- public class Ksoap2ResultParser {
- /**
- * Parses a single business object containing primitive types from the response
- * @param input soap message, one element at a time
- * @param theClass your class object, that contains the same member names and types for the response soap object
- * @return the values parsed
- * @throws NumberFormatException
- * @throws IllegalArgumentException
- * @throws IllegalAccessException
- * @throws InstantiationException
- */
- public static void parseBusinessObject(String input, Object output) throws NumberFormatException, IllegalArgumentException, IllegalAccessException, InstantiationException{
- Class theClass = output.getClass();
- for (int i = 0; i < fields.length; i++) {
- Type type=fields[i].getType();
- fields[i].setAccessible(true);
- //detect String
- String tag = "s" + fields[i].getName() + "="; //"s" is for String in the above soap response example + field name for example Name = "sName"
- if(input.contains(tag)){
- String strValue = input.substring(input.indexOf(tag)+tag.length(), input.indexOf(";", input.indexOf(tag)));
- if(strValue.length()!=0){
- fields[i].set(output, strValue);
- }
- }
- }
- //detect int or Integer
- String tag = "i" + fields[i].getName() + "="; //"i" is for Integer or int in the above soap response example+ field name for example Goals = "iGoals"
- if(input.contains(tag)){
- String strValue = input.substring(input.indexOf(tag)+tag.length(), input.indexOf(";", input.indexOf(tag)));
- if(strValue.length()!=0){
- }
- }
- }
- //detect float or Float
- if(input.contains(tag)){
- String strValue = input.substring(input.indexOf(tag)+tag.length(), input.indexOf(";", input.indexOf(tag)));
- if(strValue.length()!=0){
- }
- }
- }
- }
- }
- }
Now this class can be easily reused for parsing any response with primitive types, and it provides the result in a convenient form to work with.
Usage:
- TopGoalScores topGoalScores=new TopGoalScores();
- try {
- Ksoap2ResultParser.parseBusinessObject(soapresultmsg.getProperty(0).toString(), topGoalScores);
- // TODO Auto-generated catch block
- e.printStackTrace();
- // TODO Auto-generated catch block
- e.printStackTrace();
- // TODO Auto-generated catch block
- e.printStackTrace();
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
We know, that there is still room for improvements. The error reporting could be done in a sophisticated way for example. Or maybe we could do an implementation, that not only parses one object, but a list of objects. With this article we just wanted to introduce the basic idea.
New tutorials from Helloandroid
Recent Apps
Android on Twitter
-
@StephanieNich10 (Stephanie Nichols)#android I laughed so hard at ochocinco 's avi. Hahahaha http://t.co/MPuhhi3m
25 weeks 3 days ago -
@CarlaAtkins8 (Carla Atkins)#android Omg! This is actually f'n interesting http://t.co/JodMOehr
25 weeks 3 days ago -
@MarianMcleod12 (Marian Mcleod)#android Precisely what song is? http://t.co/YmJXU0rB
25 weeks 3 days ago -
@JoBeach15 (Jo Beach)#android haha this made me laugh, i love ted:-) http://t.co/gtcWQ79C
25 weeks 3 days ago -
@aochart3 (青ちゃ)Start playing Paradise Island on Android http://t.co/DEID0Ao5 #Android #Androidgames #Gameinsight http://t.co/e1bifSeL
25 weeks 3 days ago
Poll
Useful resources
Android Development Projects
- 3yada for Android by tmg2000
- Nonpublic project #4538058 by Barron1408
- Targeted Jobs Push Notification System by codebarron
- Android app for a service by vmuthu
- iOS and Android app for a social website by andymediavw
- HLS-esign Delivery by hls02
- Fix Zoom and Pan and image loader in android. by DevFuture
- Implement Pushnotification into an existing app by d9n169
- Andriod Application by jasminreno
- Android App Development by Aroris



