Tuesday, June 15, 2010

SOAP on Android

Some projects require to communicate with Web services.
The JDK provides tool called wsimport that generates classes from WSDL, and user works with them like with other Java classes and may not know that he works with a Web service.

But it does not work on Android... Android  SDK does not provide classes to work with Web services. So, it needs to manually work with Web services by using SOAP.

There is a good library called kSOAP 2 that is a lightweight SOAP Web service client library for constrained Java environments such as Applets or J2ME applications. There is a port of this library to Android platform that is allowed on Google code.

Weather forecast Web service
Lets try to use kSOAP 2 for getting weather forecast from the WeatherForecast Web service.

Next code calls the GetWeatherByPlaceName operation on Web service to get weather forecast for specified city for next few days

public SoapObject getWeather(String city) throws Exception {
    SoapObject request = new SoapObject("http://www.webservicex.net", "GetWeatherByPlaceName");
    request.addProperty("PlaceName", city);
        
    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.setOutputSoapObject(request);
    // It seems that it is a .NET Web service because it doesn't work without next line
    envelope.dotNet = true;

    HttpTransportSE transport = new HttpTransportSE("http://www.webservicex.net/WeatherForecast.asmx");
    transport.call("http://www.webservicex.net/GetWeatherByPlaceName", envelope);
    
    return (SoapObject) envelope.getResponse();
}

As you can see it's easy. But it needs also to parse data received from the Web service.
public List<CharSequence> getWeatherForecast(String city) throws Exception {
    SoapObject obj = getWeather(city);
    SoapObject details = (SoapObject) obj.getProperty("Details");
        
    List<CharSequence> list = new ArrayList<CharSequence>(details.getPropertyCount());
    for (int i = 0; i < details.getPropertyCount(); i++) {
        Object property = details.getProperty(i);
        if (property instanceof SoapObject) {
            SoapObject weather = (SoapObject) property;
            String day = weather.getProperty("Day").toString();
            String min = weather.getProperty("MinTemperatureF").toString();
            String max = weather.getProperty("MaxTemperatureF").toString();
                
            list.add(day + " :: " + min + "-" + max);
        }
    }
    return list;
}

Next are weather forecast for the Atlanta city, received by using this routine.
[Tuesday, June 15, 2010 :: 77-90, Wednesday, June 16, 2010 :: 73-92, Thursday, June 17, 2010 :: 73-95, Friday, June 18, 2010 :: 74-96, Saturday, June 19, 2010 :: 75-95, Sunday, June 20, 2010 :: 74-96, Monday, June 21, 2010 :: 74-96]


Note: .NET services
There are problems with .Net Web services, so it needs to set the dotNet variable of the SoapSerializationEnvelope class. Next are Java docs about it.

dotNet

public boolean dotNet
  Set this variable to true for compatibility with what seems to be  the  default encoding for .Net-Services. This  feature is an extremely ugly  hack. A much better option is to change the configuration of the  .Net-Server to standard Soap Serialization! 


Note: Weather forecast Web service
The WeatherForecast Web service works also with HTTP POST and GET requests, that don't requires using SOAP. But you should parse received XML manually. This page contains their descriptions and the Test form.

13 comments:

  1. hi can any one suggest the best way to call web service thatneed to send request in xml format exactly as the below soap, is it possible in ksoap2

    For the soap

    ?xml version="1.0" encoding="utf-8"?>
    soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    soap:Body>
    employee xmlns="http://abcd.com/">
    emp>
    Name>string/Name>
    Designation>string/Designation>
    /emp>
    /employee>
    /soap:Body>
    /soap:Envelope>

    responce will be

    ?xml version="1.0" encoding="utf-8"?>
    soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    soap:Body>
    employeeResponse xmlns="http://abcd.com/">
    employeeResult>string/employeeResult>
    /employeeResponse>
    /soap:Body>
    /soap:Envelope>

    ReplyDelete
  2. how to send the data to server and compare the values which are in database with the given parameters and return the result

    ReplyDelete
  3. This blog is nice and easy to understand. However I had trouble setting up the required jars. Here is a link to a jar which helped me,

    http://code.google.com/p/ksoap2-android/downloads/detail?name=ksoap2-android-assembly-2.4-jar-with-dependencies.jar&can=2&q=

    ReplyDelete
  4. This example is throwing a RuntimeException when it tries to retrieve temperature for the 7th day. Apparently 'Day' is an illegal property. Tried with 2 different locations "London & "Paris" and got the same thing. A problem with the returned data from the web service maybe.

    ReplyDelete
  5. Can you show us through example how to call the WCF webservice with .svn extension? I am getting big trouble to call it.Thanx in advance.

    ReplyDelete
  6. Hi,
    In this example String city showing error,can you please explain briefly
    and also my requirement is i have login page contacting username and password when you click submit button it will check this username and password available or not can you please help me

    ReplyDelete
  7. Nice for this solution i have wasted one night but now solved the issue...
    thank you

    ReplyDelete
  8. hi,

    in this, my response is coming in string. but i want to parse it in int, so i have parse it like this but still it show me "Unable to parse in int". so please let me know how can solve this?

    try
    {

    androidHttpTransport.call(SOAP_ACTION, envelope);
    SoapPrimitive responce = (SoapPrimitive)envelope.getResponse();

    String result = responce.toString();

    int final_rate = Integer.parseInt(result);
    System.out.println("Current final_result is..." + final_rate);

    rate.setText(result);


    } catch (Exception e) {
    e.printStackTrace();
    }

    ReplyDelete
  9. can any body tell me how to send soap request in json format

    ReplyDelete
  10. http://stackoverflow.com/q/19650854/2878181

    ReplyDelete
  11. Thanks Kankan .I was cordially looking for this type of article.

    ReplyDelete
  12. I have to do same Soap Parsing..but url is with "https"...so i am getting error of SSL Certificate ..!!

    How to handle "Https://" url in code given by you.??

    ReplyDelete