Consuming SOAP web services from Android

August 3, 2016
admin

Contributor: Abidur Rahman

Though SOAP based web-services are rare in these days, but there are lots of old companies whose web-services are still SOAP-based. If anyone wants to consume those services from Android, it is very important to know the procedure of consuming SOAP-based webservice. There are lots of tutorials on consuming RESTful web-services with better explanation, but there are a few tutorials on consuming SOAP web-services with a clear explanation.

In this article, we will learn how to consume SOAP web services from Android. Before starting code, we have to collect some information:

  • SOAP_ACTION
  • METHOD_NAME
  • NAMESPACE
  • URL
  • Parameter List
  • Request XML/ SOAP_BODY/ SOAP_MESSAGE (for Nested Parameters and Multiple Namespaces)

Now, the question is how can we get these information? if your client or service provider give you all the information, you won’t need anything. But if they don’t, then follow the process given below:

Suppose, you have to consume the data from this service: http://www.w3schools.com/webservices/tempconvert.asmx

This is the URL!!

Click on it, you can see a link named “Service Description” and a list of Method Name(s). So, we can get the METHOD_NAMEs from here.
Now, click on the “Service Description”.

abid's blog pic 1

You can see the NAME_SPACE there. For nested parameters, there can be multiple namespaces. So, a question may arise. “How can I find other namespaces?”. Okay!! I will discuss it later.

abid's blog pic 2

You can see the SOAP_ACTIONs here depending on the METHOD_NAME. So, be careful to choose the SOAP_ACTION!! You can also get the Parameter List here depending on the METHOD_NAME.

Okay we have got all (not all for the complex web services!!!) the information to consume soap web services from Android. Let’s code !!!

Sample Project

Start a new Android project and configure it as you please. Feel free to use your favorite IDE, but for this tutorial I’ll be using Android Studio.

In the project’s manifest file, you need to specify that the application is allowed to connect to the internet. So, add:

<uses-permission android:name="android.permission.INTERNET"/>

We will use a library named “kSOAP” which is an elegant, lightweight, and efficient SOAP client library. The library is open source, easy to use, and it will save you from the hassle of coding a custom parser.

To sync kSOAP library with your project, add these lines (bolded text) to your app’s build.gradle file:

apply plugin: 'com.android.application'

android {
 compileSdkVersion 23
 buildToolsVersion "23.0.2"

defaultConfig {
 applicationId "com.nascenia.soap"
 minSdkVersion 15
 targetSdkVersion 23
 versionCode 1
 versionName "1.0"
 }
 buildTypes {
 release {
 minifyEnabled false
 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
 }
 repositories {
 maven { url 'http://ksoap2-android.googlecode.com/svn/m2-repo' }
 }
 }
}

dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 compile 'com.android.support:appcompat-v7:23.1.1'
 compile 'com.google.code.ksoap2-android:ksoap2-android:3.3.0'
}

Now, set SOAP_ACTION, METHOD_NAME and NAMESPACE variables in your activity class:

 .
    .
    .

public class MainActivity extends AppCompatActivity {

   private static final String SOAP_ACTION = "http://www.w3schools.com/webservices/CelsiusToFahrenheit";
   private static final String METHOD_NAME = "CelsiusToFahrenheit";
   private static final String NAMESPACE = "http://www.w3schools.com/webservices/";

   @Override
   protected void onCreate(Bundle savedInstanceState) {
    .
    .
    .

Now, create an AsyncTask, and add these doInBackground()’s codes to your doInBackground() method.

private class myAsyncTask extends AsyncTask<Void, Void, Void> {


   @Override
   protected Void doInBackground(Void... params) {

     String URL = "http://www.w3schools.com/webservices/tempconvert.asmx";

     //for linear parameter
     SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
     request.addProperty("Celsius", "48"); // adding method property here serially

     SoapSerializationEnvelope envelope = new      SoapSerializationEnvelope(SoapEnvelope.VER11);
     envelope.implicitTypes = true;
     envelope.setOutputSoapObject(request);
     envelope.dotNet = true;
 
     HttpTransportSE httpTransport = new HttpTransportSE(URL);
     httpTransport.debug = true;

     try {
        httpTransport.call(SOAP_ACTION, envelope);
     } catch (HttpResponseException e) {
        // TODO Auto-generated catch block
        Log.e("HTTPLOG", e.getMessage());
        e.printStackTrace();
     } catch (IOException e) {
        // TODO Auto-generated catch block
        Log.e("IOLOG", e.getMessage());
        e.printStackTrace();
     } catch (XmlPullParserException e) {
        // TODO Auto-generated catch block
        Log.e("XMLLOG", e.getMessage());
        e.printStackTrace();
     } //send request

     Object  result = null;
     try {
        result = (Object )envelope.getResponse();
        Log.i("RESPONSE",String.valueOf(result)); // see output in the console
     } catch (SoapFault e) {
        // TODO Auto-generated catch block
        Log.e("SOAPLOG", e.getMessage());
        e.printStackTrace();
     }
     return null;
  }
}

Now execute your AsyncTask from onCreate method to see the output in the console.

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

   myAsyncTask myRequest = new myAsyncTask();
   myRequest.execute();
}

For Nested Parameters and Multiple Namespaces

For the complex web services, we need SOAP_BODY/ SOAP_MESSAGE/ REQUEST_XML.

There is an elegant and efficient SOAP browser online: http://wsdlbrowser.com/

Copy the URL of your web service, and add “?wsdl” at the end of the URL and then browse.
You should see the METHOD_NAME on the left side. Click on one of the METHOD_NAMEs which you want. You will see REQUEST_XML there. It is the SOAP_BODY or SOAP_MESSGAE.

Consuming SOAP web services from Android

  • NAMESPACE name – Value of “xmlns:ns1”. If there are multiple namespaces, it will be indicated by ns1, ns2 and so on.
  • METHOD_NAME – indicated by the 1st arrow.
  • Parameter Name – indicated by the 2nd arrow.

REQUEST_XML:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="NAMESPACE1" xmlns:ns2="NAMESPACE2">
  <SOAP-ENV:Body>
    <ns1:GetTurnover>
      <ns1:sessionID>0</ns1:sessionID>
      <ns1:selection>
        <ns2:EndDate>?</ns2:EndDate>
        <ns2:StartDate>?</ns2:StartDate>
      </ns1:selection>
    </ns1:GetTurnover>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

CODE:

// for nested parameters and multiple namespaces.
SoapObject request = new SoapObject(NAMESPACE1, METHOD_NAME);
PropertyInfo p = new PropertyInfo();
p.setNamespace(NAMESPACE1);
p.setType(PropertyInfo.STRING_CLASS);
p.setName("sessionID");
p.setValue(“value”);
request.addProperty(p);

SoapObject selection = new SoapObject(NAMESPACE1,"selection");
PropertyInfo EndDate = new PropertyInfo();
EndDate.setNamespace(NAMESPACE2);
EndDate.setType(PropertyInfo.STRING_CLASS);
EndDate.setName("EndID");
EndDate.setValue("value");
selection.addProperty(EndDate);

PropertyInfo StartDate = new PropertyInfo();
StartDate.setNamespace(NAMESPACE2);
StartDate .setType(PropertyInfo.STRING_CLASS);
StartDate.setName("StartID");
StartDate .setValue("value");
selection.addProperty(StartDate);

request.addSoapObject(selection);

DONE!!!

I hope that helps. Please check some other blogs on web and mobile app development.

9 Comments. Leave new

thx bro, you save my live

Reply

It looks great but do you have any repository on GitHub or where can I find this source code.

Reply

You can check our GitHub repo https://github.com/nascenia

Reply
Tanmay Sonawane
December 26, 2017 11:38 am

How to generate request without header using ksoap2 in android.
using above code iam generating request like this.

admin

which is fine if these don’t have tag included then it will run on soapUI.
i need request like below mention.

admin

hope you help me to resolve these
thank you,
tanmay

Reply
vishwa pratap
July 9, 2018 4:19 pm

Hi I am following your code for nested tag ,

0

?
?

in my code having same structure in my code.
but i got the following error .

{“s:Envelope”:{“xmlns:s”:”http:\/\/schemas.xmlsoap.org\/soap\/envelope\/”,”s:Body”:{“s:Fault”:{“faultcode”:{“content”:”a:DeserializationFailed”,
“xmlns:a”:”http:\/\/schemas.microsoft.com\/net\/2005\/12\/windowscommunicationfoundation\/dispatcher”},”faultstring”:{“content”:”The formatter
threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter
http:\/\/tempuri.org\/cost:_customer. The InnerException message was ‘Error in line 1 position 486. Element
‘http:\/\/tempuri.org\/cost:_customer’ contains data from a type that maps to the name ‘http:\/\/tempuri.org\/cost:_customer’.
The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver if you are using
DataContractSerializer or add the type corresponding to ‘_customer’ to the list of known types – for example, by using the
KnownTypeAttribute attribute
or by adding it to the list of known types passed to the serializer.’. Please see InnerException for more details.”,”xml:lang”:”en-GB”}}}}}
I will be great pleasure if i get any suggestion from your side thanks..

Reply
vishwa pratap
July 10, 2018 12:00 pm

hi..I am following your code for nested properties inside a tag but i get following issues.

{“s:Envelope”:{“xmlns:s”:”http:\/\/schemas.xmlsoap.org\/soap\/envelope\/”,”s:Body”:{“s:Fault”:{“faultcode”:{“content”:”a:DeserializationFailed”,”xmlns:a”:”http:\/\/schemas.microsoft.com\/net\/2005\/12\/windowscommunicationfoundation\/dispatcher”},”faultstring”:{“content”:”The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http:\/\/tempuri.org\/Navision:_customer. The InnerException message was ‘Error in line 1 position 576. Element ‘http:\/\/tempuri.org\/aa:_customer’ contains data from a type that maps to the name ‘http:\/\/tempuri.org\/aa:_customer’. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver if you are using DataContractSerializer or add the type corresponding to ‘_customer’ to the list of known types – for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to the serializer.’. Please see InnerException for more details.”,”xml:lang”:”en-GB”}}}}}

Reply

Thanks. You have been the start of my research in ksoap2. And after a lot of research and starting from here i could made it. Thanks a lot

Reply
Mostaq Hossain
July 8, 2019 11:11 am

Thanks to the contributor!!!
In stackoverflow there have many solution or way on this Soap api. But your writings is very much precise and pretty helpful to get proper direction. Thanks man!

Reply

Thanks for your appreciation. We are happy to be of your help.

Let us know if we can shed light on anything else which might help.

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.