bimbima

Daily life experience of ayurvedic medicines, complementary therapies.

Android: Calling Web Service with complex types

Calling web service on Android is possible with KSOAP2 (ksoap2-android-assembly-2.4-jar-with-dependencies.jar)  or you can write you own soap message formatter and can make http call using android apache http classes.

In this post i am going to explain calling web service using ksoap lib for dotnet service. This web service is hosted at http://bimbim.in/Sample/TestService.asmx. You can use this for your reference because Android emulator is not connecting with local web development server which comes with Visual Studio ( i don’t know exact reason).

 

For complete understanding i will suggest you to download complete android code from here 

Bimbimin.Android.Webservice.Client.rar (177.05 kb) and debug it using my web service URL.

 

First i will brief web service which i will use to explain web service calling.

I have created one serializable class Person with 4 attributes of different types in asp.net

[Serializable]
public class Person
{
    private string _name = string.Empty;
    private int _age = 0;
    private float _salary = 100000.0f;
    private DateTime? _dob = new DateTime(1980, 01, 15);
 
    public float Salary
    {
        get { return _salary; }
        set { _salary = value; }
    }
    public DateTime? Dob
    {
        get { return _dob; }
        set { _dob = value; }
    }
 
    public int Age
    {
        get { return _age; }
        set { _age = value; }
    }
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
 
}

and create two web method in web service GetSingle and SetValue.

public class TestService : System.Web.Services.WebService
{
 
    [WebMethod]
    public string HelloWorld()
    {
        return "Hello World";
    }
 
    [WebMethod]
    public Person GetSingle()
    {
        Person person = new Person();
        person.Name = "bimbim.in";
        person.Age = 30;
        person.Dob = new DateTime(1980, 01, 15);
        person.Salary = 50000f;
 
        return person;
    }
 
    [WebMethod]
    public bool SetValue(Person value)
    {
        bool result = false;
        if (value != null)
        {
            result = true; 
        }
 
        return result;
    }
}

One takes Person as input parameter and other return Person object.

You can see wsdl for web service by http://bimbim.in/Sample/TestService.asmx?wsdl or just by using http://bimbim.in/Sample/TestService.asmx in browser you can see method list and by clicking method name you can see all details of that method.

Now i will explain how to call this web service method in Android using Ksoap 2. Although this lib has some bug and limitation but it is very useful.

In android application first we have to create a java class for Web service Person structure and we have to implement KvmSerializable interface in this class. KvmSerializable is used to transform soap message by ksoap library.

/**
 * 
 */
package bimbimin.android.webservice.dto;
 
import java.util.Date;
import java.util.Hashtable;
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
 
/**
 * @author Bimbim
 * 
 */
public class Person implements KvmSerializable
{
    public static Class PERSON_CLASS = Person.class;
    private String _name = "";
    private int _age = 0;
    private float _salary = 100000.0f;
    private Date _dob = new Date(1980, 01, 15);
 
    public Person()
    {
    }
 
    public Person(SoapObject obj)
    {
        this._name = obj.getProperty("Name").toString();
        this._age = Integer.parseInt(obj.getProperty("Age").toString());
        this._salary = Float.parseFloat(obj.getProperty("Salary").toString());
 
        String dob = obj.getProperty("Dob").toString();
        // Change date string according to your local
        String[] parts = dob.split("T")[0].split("-");
        this._dob = new Date(Date.UTC(Integer.parseInt(parts[0]), Integer
                .parseInt(parts[1]), Integer.parseInt(parts[2]), 0, 0, 0));
    }
 
    /**
     * @return the _name
     */
    public String get_name()
    {
        return _name;
    }
 
    /**
     * @param name
     *            the _name to set
     */
    public void set_name(String name)
    {
        _name = name;
    }
 
    /**
     * @return the _age
     */
    public int get_age()
    {
        return _age;
    }
 
    /**
     * @param age
     *            the _age to set
     */
    public void set_age(int age)
    {
        _age = age;
    }
 
    /**
     * @return the _salary
     */
    public float get_salary()
    {
        return _salary;
    }
 
    /**
     * @param salary
     *            the _salary to set
     */
    public void set_salary(float salary)
    {
        _salary = salary;
    }
 
    /**
     * @return the _dob
     */
    public Date get_dob()
    {
        return _dob;
    }
 
    /**
     * @param dob
     *            the _dob to set
     */
    public void set_dob(Date dob)
    {
        _dob = dob;
    }
 
    /* (non-Javadoc)
     * @see org.ksoap2.serialization.KvmSerializable#getProperty(int)
     */
    @Override
    public Object getProperty(int index)
    {
        Object object = null;
        switch (index)
        {
        case 0:
        {
            object = this._name;
            break;
        }
        case 1:
        {
            object = this._age;
            break;
        }
        case 2:
        {
            object = this._salary;
            break;
        }
        case 3:
        {
            object = this._dob;
            break;
        }
        }
        return object;
    }
 
    /* (non-Javadoc)
     * @see org.ksoap2.serialization.KvmSerializable#getPropertyCount()
     */
    @Override
    public int getPropertyCount()
    {
        // TODO Auto-generated method stub
        return 4;
    }
 
    /* (non-Javadoc)
     * @see org.ksoap2.serialization.KvmSerializable#
     * getPropertyInfo(int, java.util.Hashtable, 
     * org.ksoap2.serialization.PropertyInfo)
     */
    @Override
    public void getPropertyInfo(int index, Hashtable arg1,
            PropertyInfo propertyInfo)
    {
        // TODO Auto-generated method stub
        switch (index)
        {
        case 0:
        {
            propertyInfo.name = "Name";
            propertyInfo.type = PropertyInfo.STRING_CLASS;
            break;
        }
        case 1:
        {
            propertyInfo.name = "Age";
            propertyInfo.type = PropertyInfo.INTEGER_CLASS;
            break;
        }
        case 2:
        {
            propertyInfo.name = "Salary";
            propertyInfo.type = Float.class;
            break;
        }
        case 3:
        {
            propertyInfo.name = "Dob";
            propertyInfo.type = Date.class;
            break;
        }
        }
    }
 
    /* (non-Javadoc)
     * @see org.ksoap2.serialization.KvmSerializable#setProperty
     * (int, java.lang.Object)
     */
    @Override
    public void setProperty(int index, Object obj)
    {
        // TODO Auto-generated method stub
        switch (index)
        {
        case 0:
        {
            this._name = obj.toString();
            break;
        }
        case 1:
        {
            this._age = Integer.parseInt(obj.toString());
            break;
        }
        case 2:
        {
            this._salary = Float.parseFloat(obj.toString());
            break;
        }
        case 3:
        {
            this._dob = new Date(Date.parse(obj.toString()));
            break;
        }
        }
    }
 
}

I have created four attributes in this class as web service class and Implemented KvmSerializable 4 methods.

  1. public int getPropertyCount(): return attribute count in our case it is 4.
  2. public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo propertyInfo): Set propertyInfo attribute name and type, see above code listing.
  3. public Object getProperty(int index): Called by ksoap when formatting soap message.
  4. public void setProperty(int index, Object obj): Called by ksoap when created instance of classes from soap message response.

Note: Please used same sequence while writing these method as you have used in getPropertyInfo method.

Now make call using ksoap library

 
package bimbimin.android.webservice.client;
 
import java.io.IOException;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.Marshal;
import org.ksoap2.serialization.MarshalDate;
import org.ksoap2.serialization.MarshalFloat;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import bimbimin.android.webservice.dto.Person;
 
public class ServiceCall
{
    private static final String SOAP_ACTION = 
        "http://tempuri.org/";
    private static final String NAMESPACE = 
        "http://tempuri.org/";
    private static final String URL = 
        "http://bimbim.in/Sample/TestService.asmx";
 
    private boolean isResultVector = false;
 
    protected Object call(String soapAction, 
            SoapSerializationEnvelope envelope)
    {
        Object result = null;
        
        final HttpTransportSE transportSE = new HttpTransportSE(URL);
        
        transportSE.debug = false;
 
        // call and Parse Result.
        try
        {
            transportSE.call(soapAction, envelope);
            if (!isResultVector)
            {
                result = envelope.getResponse();
            } else
            {
                result = envelope.bodyIn;
            }
        } catch (final IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (final XmlPullParserException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (final Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }
 
    public Person CallGetSingle()
    {
        final String sGetSingle = "GetSingle";
 
        // Create the outgoing message
        final SoapObject requestObject = 
            new SoapObject(NAMESPACE, sGetSingle);
        // Create soap envelop .use version 1.1 of soap
        final SoapSerializationEnvelope envelope = 
            new SoapSerializationEnvelope(
                SoapEnvelope.VER11);
        envelope.dotNet = true;
        // add the outgoing object as the request
        envelope.setOutputSoapObject(requestObject);
        envelope.addMapping(NAMESPACE, 
                Person.PERSON_CLASS.getSimpleName(),
                Person.PERSON_CLASS);
 
        // call and Parse Result.
        final Object response = this.call(
                SOAP_ACTION + sGetSingle, envelope);
        Person result = null;
        if (response != null)
        {
            result = new Person((SoapObject) response);
        }
 
        return result;
    }
 
    public Boolean CallSetValue(Person param)
    {
        final String sSetValue = "SetValue";
        final String svalue = "value";
        // Create the outgoing message
        final SoapObject requestObject = 
            new SoapObject(NAMESPACE, sSetValue);
        // Set Parameter type String
        requestObject.addProperty(svalue, param);
        // Create soap envelop .use version 1.1 of soap
        final SoapSerializationEnvelope envelope = 
            new SoapSerializationEnvelope(
                SoapEnvelope.VER11);
        envelope.dotNet = true;
        // add the outgoing object as the request
        envelope.setOutputSoapObject(requestObject);
        envelope.addMapping(NAMESPACE, 
                Person.PERSON_CLASS.getSimpleName(),
                Person.PERSON_CLASS);
        // Register Marshaler
        // For date marshaling
        Marshal dateMarshal = new MarshalDate();
        dateMarshal.register(envelope);
        // For float marshaling
        Marshal floatMarshal = new MarshalFloat();
        floatMarshal.register(envelope);
        // call and Parse Result.
        final Object response = this.call(
                SOAP_ACTION + sSetValue, envelope);
        Boolean result = null;
        if (response != null)
        {
            try
            {
                if (response != null
                        && response.getClass() == 
                            org.ksoap2.serialization.SoapPrimitive.class)
                {
                    result = Boolean.parseBoolean(response.toString());
                }
            } catch (Exception e)
            {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
 
        return result;
    }
}

 

To call web service with ksoap you have to first create SoapSerializationEnvelope envelope. add soap request SoapObject , add class mapping and add type marshalar which are not given in PropertyInfo class.

        // Create the outgoing message
        final SoapObject requestObject = 
            new SoapObject(NAMESPACE, sSetValue);
        // Set Parameter type String
        requestObject.addProperty(svalue, param);
        // Create soap envelop .use version 1.1 of soap
        final SoapSerializationEnvelope envelope = 
            new SoapSerializationEnvelope(
                SoapEnvelope.VER11);
        envelope.dotNet = true;
        // add the outgoing object as the request
        envelope.setOutputSoapObject(requestObject);
        envelope.addMapping(NAMESPACE, 
                Person.PERSON_CLASS.getSimpleName(),
                Person.PERSON_CLASS);
        // Register Marshaler
        // For date marshaling
        Marshal dateMarshal = new MarshalDate();
        dateMarshal.register(envelope);
        // For float marshaling
        Marshal floatMarshal = new MarshalFloat();
        floatMarshal.register(envelope);

 

and finally make http request using HttpTransportSE class

        final HttpTransportSE transportSE = new HttpTransportSE(URL);
        
        transportSE.debug = false;
 
        // call and Parse Result.
        try
        {
            transportSE.call(soapAction, envelope);
            if (!isResultVector)
            {
                result = envelope.getResponse();
            } else
            {
                result = envelope.bodyIn;
            }
        } catch (final IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 

For complete understanding i will suggest you to download complete android code from here 

Bimbimin.Android.Webservice.Client.rar (177.05 kb) and debug it using my web service URL.