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
-
@Idevicegazette (iDevice Gazette)
GSM-to-Skype bridge lets you lose those roaming fees http://bit.ly/lbRJeh #android
11 years 45 weeks ago -
@tommy_banane (tom b.)
RT @AndroidFavorite: #Android New Desktop Android Market Is Live, Adds Several New Features http://zorr0.nl/lFwXNz
11 years 45 weeks ago -
@dwilliams5 (Dennis Williams)
just completed a runtastic run of 3.02 km in 40 min 11 s with #runtastic #Android App: http://tinyurl.com/5tvrpe3
11 years 45 weeks ago -
@S_Pinz (Spinz!)
RT @Androidheadline: Out of box #LG Optimus 3D got Quadrant 2420 score. Thanks @blink_c #io2011 #android http://twitpic.com/4whkdz
11 years 45 weeks ago -
@tayaitapps (Taya IT)
Next Google TV Looks A Lot Like Android http://t.co/dvlTim3 via @alleyinsider #google #apple #android #tv #honeycomb
11 years 45 weeks ago
Poll
Useful resources
Android Development Projects
- iOS/Android Developer to take older Games and bring them Current
- Android apps developer - need to finish urgent.
- Buliding MobileApp For onlie order
- looking for android APP developers
- Create an ecommerce app
- text-to voice for smartphones IOS - GOOGLE - HARMONY - AND ALEXA
- Optimize Images on App
- Create small feature with drag-drop text for Android
- Scouting for advanced website and Mobile apps developers. Potential Long-term contract.
- BLACK SCREEN