KSoap Android Web Service Tutorial With Sample Code

摘要:KSoap Android Web Service Tutorial With Sample Code

A few months ago I was engaged into working with Android and I wanted to make an application that will communicate with the server via .NET SOAP web services, but I soon found out that I will need a library to do the "donkey work for me". Unfortunately, what Visual Studio was doing for me behind the scenes when importing WSDL document, was not present in Android. That means that, I would either parse the WSDL XML myself, or use an external library. After little search, I came up to KSOAP, which looked like a promising library. But soon I got into lot of trouble to make it work. 
Partly because there was no complete tutorial with the WHOLE sample WORKING code for passing complex objects as parameters and/or arrays as return values (read this post for returning arrays of objects with KSOAP ), I spent many hours debugging exceptions which were filled with nulls and poor documentation in first place. 

Therefore I decided to publish the code I managed to make it work, so many lives will be saved :-) hopefully. I almost forgot about the idea of publishing my code, but today I got some e-mails from some of the Google groups where I was begging for help when I was developing the Android application. So, tortured developer souls, a complete working code for working with the KSOAP library for Android:

Scenario:
We will assume that we want to write a web service that retrieves the details about a given Category by its Id. So, in .NET, the service signature would be:


[Web Method]
public Category GetCategoryById(Category C);


The class that we want to work with has 3 properties: CategoryId, Name and Description. But in order to use it with KSOAP, we need to implement the KvmSerializable interface (Code below is inJava):

 


package CommonObjects;

import java.util.Hashtable;
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;

/**
 * 
 * @author Vladimir
 * Represents the Category object. KvmSerializable interface needs to be 
 * implemented for performing serialization.
 */
public class Category implements KvmSerializable
{
    public int CategoryId;
    public String Name;
    public String Description;
    
    public Category(){}
    

    public Category(int categoryId, String name, String description) {
        
        CategoryId = categoryId;
        Name = name;
        Description = description;
    }


    public Object getProperty(int arg0) {
        
        switch(arg0)
        {
        case 0:
            return CategoryId;
        case 1:
            return Name;
        case 2:
            return Description;
        }
        
        return null;
    }

    public int getPropertyCount() {
        return 3;
    }

    public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
        switch(index)
        {
        case 0:
            info.type = PropertyInfo.INTEGER_CLASS;
            info.name = "CategoryId";
            break;
        case 1:
            info.type = PropertyInfo.STRING_CLASS;
            info.name = "Name";
            break;
        case 2:
            info.type = PropertyInfo.STRING_CLASS;
            info.name = "Description";
            break;
        default:break;
        }
    }

    public void setProperty(int index, Object value) {
        switch(index)
        {
        case 0:
            CategoryId = Integer.parseInt(value.toString());
            break;
        case 1:
            Name = value.toString();
            break;
        case 2:
            Description = value.toString();
            break;
        default:
            break;
        }
    }
}


All methods in this class are members of the KvmSerializable Interface, and are used to tell KSOAPhow to map the properties, read them and write them.

Now, the actual web service call:
 


public void WebServiceCallExample()
    {
        String NAMESPACE = "http://vladozver.org/";
        String METHOD_NAME = "GetCategoryById";
        String SOAP_ACTION = "http://vladozver.org/GetCategoryById";
        String URL = "http://192.168.1.3/VipEvents/Services/CategoryServices.asmx";
        
        SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME);
        
        /*
         * Create Category with Id to be passed as an argument
         * 
         * */
        Category C = new Category();
        C.CategoryId = 1;
        
        /*
         * Set the category to be the argument of the web service method
         * 
         * */
        PropertyInfo pi = new PropertyInfo();
        pi.setName("C");
        pi.setValue(C);
        pi.setType(C.getClass());
        Request.addProperty(pi);
        
        /*
         * Set the web service envelope
         * 
         * */
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.dotNet = true;
        envelope.setOutputSoapObject(Request);
        
        envelope.addMapping(NAMESPACE, "Category",new Category().getClass());
        AndroidHttpTransport androidHttpTransport = new AndroidHttpTransport(URL);
        /*
         * Call the web service and retrieve result ... how luvly <3
         * 
         * */
        try
        {
            androidHttpTransport.call(SOAP_ACTION, envelope);
            SoapObject response = (SoapObject)envelope.getResponse();
            C.CategoryId =  Integer.parseInt(response.getProperty(0).toString());
            C.Name =  response.getProperty(1).toString();
            C.Description = (String) response.getProperty(2).toString();
            TextView tv = (TextView)findViewById(R.id.TextView01);
            tv.setText("CategoryId: " +C.CategoryId + " Name: " + C.Name + " Description " + C.Description);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }


In order to use this code, make sure that you replace the first three variables in this method with your own. NOTE: The SOAP_ACTION could actually be computed as NAMESPACE + METHOD_NAME

In the lines about the property info, I show how to actually pass a Category class complex object to KSOAP.
 


PropertyInfo pi = new PropertyInfo();
        pi.setName("Category");
        pi.setValue(C);
        pi.setType(C.getClass());
        Request.addProperty(pi);


Regarding the return type, if your web method returns a complex object (such as ours), you need to tell KSOAP how to handle the response. That is done with the following code:
 


envelope.addMapping(NAMESPACE, "Category",new Category().getClass());


This part of the code is the actual retrieval of the response:


androidHttpTransport.call(SOAP_ACTION, envelope);
            SoapObject response = (SoapObject)envelope.getResponse();
            C.CategoryId =  Integer.parseInt(response.getProperty(0).toString());
            C.Name =  response.getProperty(1).toString();
            C.Description = (String) response.getProperty(2).toString();


For further reading, see my post about returning an array of complex objects with KSOAP


人生到處知何似
應似飛鴻踏雪泥