Making the Call
Once all the setup work is complete, the actual call is simple:
httpt.call("", envelope);
That means "make a call to the web service specified in the transport using the information in envelope". If your web service interface had several subinterfaces on it, in theory they could be differentiated with the first parameter, but the implementation of this functionality seems broken, so we send the full path into the constructor for the transport.
That one simple call tells kSOAP to build (serialize) an XML request, send that request to the target specified in the httpTransport object, receive a response, and parse (deserialize) that response into kObject objects.
Parsing the Response
At this point, kSOAP has the response stored as objects in a field of SoapSerializationEnvelope called bodyIn. We need to get that value out so that we can work with it:
SoapObject body = (SoapObject)envelope.bodyIn;
The actual response data is represented as properties attached to the bodyIn instance. The best way to access it is to use the index of the return parameter. The first return value is property number 0, and it counts up from there. So if all your web service returned was a list of names, the following code would give you access to those names, assuming you had assigned bodyIn to the variable body.
Vector names = (Vector)body.getProperty(0);
Just remember that kSOAP makes no assumptions about your data, so while you might expect the Vector (or any return value) to contain String variables, it will actually contain SOAPObject variables that you will have to translate to Strings before using.
Complex Data Types
While the above information will help you if you can map your complex data types into simple data types, it does not help you much if you need to represent complex data types natively in the request, or they are returned natively in the response. The kSOAP library has a mechanism to deal with this.
To work with complex data types natively, you need to implement the KvmSerializable interface. This requires the following methods:
getPropertyCount() getPropertyInfo(int index, Hashtable properties, PropertyInfo info) getProperty(int index) setProperty(int index, Object v) register(SoapSerializationEnvelope envelope)
The method getPropertyCount is used to tell kSOAP how many properties are required to represent the members of this class. So a class with name, address, phone should return three when getPropertyCount() is called.
The method getPropertyInfo takes the property index you assigned (you assign an index to each property -- so in case we used for get PropertyCount(), name could be zero, address one, and phone two), and you return the name of the object and what type it is. The type is an enumeration provided in the kSOAP libraries -- specifically in the PropertyInfo class of the serialization library. If the member variable being referenced is itself a complex object, then its members will be in the properties hash table.
The method getProperty simply returns an instance of Object that represents the member referred to in the index parameter.
The method setProperty sets the property referred to by index to the value of v. Type checking in this one case is your responsibility, which makes sense since kSOAP has no way of knowing what you intended.
The method register tells kSOAP that when it sees a specific XML tag, it should assume that this class is the one that represents that XML element, and should serialize the XML into an instance of this class. To do this, you need to call one more kSOAP method:
envelope.addMapping(Namespace, XML Tag, Java Class);
After register is called, any time kSOAP sees the XML tag within the appropriate Namespace, it will create an instance of the Java Class passed in, and use setProperty()to fill the data in. The class must implement kvmSerializable for this to work without errors.
For most uses, since envelope.addMapping() is called inside the register routine of the class implementing kvmSerializable, you can just send this.getClass() as the third parameter.
Then you call register after you create your request object, and you do not have to think about it again. You can use the get/setProperty to access the variables, or you can create accessors that are more user-friendly to get and set from within your own code.
So the steps to create a kvmSerializable interface are fill in the get and set routines, create the register routine -- with addMapping as the core of the routine. Then in your main routine, you can call register to map from an XML type to your class.
Conclusion
That's really is all there is to harnessing the power of SOAP from your mobile devices. The kSOAP architecture takes care of serialization and deserialization of XML, handles all communications, and presents you with SoapObject elements to use. The only part that is tough to get your head around is that you must know what's coming back from the Web Service call before execution so that you can handle the response accordingly.