Saturday 25 January 2014

Populate spinners using object returned by soap web service in android.

Here we populate two spinners with strings returned from soap object web service depend upon item selected in first spinner we call the second service and display values in second spinner.

If your web service response is string array and you need to populate only one spinner check this link







Step 1: Design your layout file. Here I've given simple design with two spinners.

Activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="25dp"
android:text="@string/country"
android:textAppearance="?android:attr/textAppearanceLarge" />

<Spinner
android:id="@+id/spinner1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView1"
android:layout_below="@+id/textView1"
android:layout_marginTop="25dp" />

<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/spinner1"
android:layout_below="@+id/spinner1"
android:layout_marginTop="26dp"
android:text="@string/state"
android:textAppearance="?android:attr/textAppearanceLarge" />

<Spinner
android:id="@+id/spinner2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView2"
android:layout_below="@+id/textView2"
android:layout_marginTop="26dp" />

</RelativeLayout>

Step 2: Add uses permission Internet in your project manifest file.

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exam.blog"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET"/>

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.exam.blog.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

Step 3:Include the KSOAP2 jar file in to your project.
Right click project ⇒ Properties ⇒ Java build path ⇒ Libraries Tab ⇒ Add External Jars ⇒ browse and add KSOAP2 Jar file.

Step 4: create a new class file in your package and name it as Bean.

Bean.java:

package com.exam.twospinner;

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

public class Bean implements KvmSerializable
{
public String Country;
public String State;

public Bean(){}

public Bean(String Country,String State) {
this.Country= Country;
this.State=State;
}

@Override
public Object getProperty(int arg0) {
switch(arg0)
{
case 0:
return Country;
case 1:
return State;
}
return null;
}

@Override
public int getPropertyCount() {
return 2;
}
@Override

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

@Override
public void setProperty(int index, Object value) {
switch(index)
{
case 0:
Country= value.toString();
break;
case 1:
State= value.toString();
break;
default:
break;
}
}
}

Step 5: Then in your main class copy this code.

MainActivity.java :

package com.exam.blog;

import java.io.IOException;
import java.util.Arrays;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;

public class MainActivity extends Activity {

String[] stringArray,stringArray2;
String country;

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

//Asynctask class for webservice to populate first spinner


class country extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(MainActivity.this);

@Override
protected void onPreExecute() {
this.dialog.setMessage("Loading data");
this.dialog.show();
}

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

final String SOAP_ACTION = "http://tempuri.org/GetCountryDetails";
final String METHOD_NAME = "GetCountryDetails";
final String NAMESPACE = "http://tempuri.org/";
final String URL = "http://192.168.1.1/test/service.asmx";

SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME);
Bean C = new Bean();
PropertyInfo pi = new PropertyInfo();
pi.setName("Bean");
pi.setValue(C);
pi.setType(C.getClass());
Request.addProperty(pi);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;

envelope.setOutputSoapObject(Request);
envelope.addMapping(NAMESPACE, "Bean",new Bean().getClass());
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.debug = true;

try {
System.out.println("Request:"+Request);
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapObject response = (SoapObject) envelope.getResponse();
System.out.println("MainActivity.onCreate()"+response);
envelope.addMapping(NAMESPACE, "Bean",new Bean().getClass());
androidHttpTransport.call(SOAP_ACTION, envelope);
Bean[] countrylist = new Bean[response.getPropertyCount()];

for (int j = 0; j < countrylist.length; j++) {
SoapObject pii = (SoapObject) response.getProperty(j);
Bean beanobject = new Bean();
beanobject.Country = pii.getProperty(0).toString();
countrylist[j] = beanobject;
System.out.println("person: " + beanobject.Country);
}

int i = 0;
stringArray = new String[countrylist.length];
for (i = 0; i < countrylist.length; i++) {
stringArray[i] = Arrays.asList(countrylist[i].Country).toString().replace("[", "").replace("]", "");
System.out.println("stringarray: " + stringArray);
}
}
catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(Void result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
spinner1meth();
}
}

//Method for populating spinner 1

public void spinner1meth(){

Spinner spinner1 = (Spinner) findViewById(R.id.spinner1);

ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, stringArray);
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner1.setAdapter(adapter1);
spinner1.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
@Override
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
country= (String) parent.getItemAtPosition(pos);

new state().execute();

}
});
}

//Asynctask class for webservice to populate second spinner

class state extends AsyncTask<Void, Void, Void> {

private final ProgressDialog dialog = new ProgressDialog(MainActivity.this);

@Override
protected void onPreExecute() {
this.dialog.setMessage("Loading data");
this.dialog.show();
}

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

final String NAMESPACE = "http://tempuri.org/";
final String URL = "http://192.168.1.1/test/service.asmx";
final String SOAP_ACTION = "http://tempuri.org/GetStateDetails";
final String METHOD_NAME = "GetStateDetails";

SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("sCountry", country);
Bean C = new Bean();
PropertyInfo pi = new PropertyInfo();
pi.setName("Bean");
pi.setValue(C);
pi.setType(C.getClass());
request.addProperty(pi);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
envelope.addMapping(NAMESPACE, "Bean",new Bean().getClass());
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.debug = true;

try {
System.out.println("response" + request);
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapObject response = (SoapObject) envelope.getResponse();

Log.i("myApp", response.toString());
System.out.println("response" + response);

envelope.addMapping(NAMESPACE, "Bean",new Bean().getClass());
androidHttpTransport.call(SOAP_ACTION, envelope);
Bean[] statelist = new Bean[response.getPropertyCount()];

for (int j = 0; j < statelist.length; j++) {
SoapObject pii = (SoapObject) response.getProperty(j);
Bean beanobject = new Bean();
beanobject.State = pii.getProperty(1).toString();
statelist[j] = beanobject;
System.out.println("person1: " + beanobject.State);
}

int i = 0;
stringArray2 = new String[statelist.length];
for (i = 0; i < statelist.length; i++) {
stringArray2[i] = Arrays.asList(statelist[i].State).toString().replace("[", "").replace("]", "");
System.out.println("stringarray: " + stringArray2);
}
return null;
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}


@Override
protected void onPostExecute(Void result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
spinner2meth();
}
}

//Method for populating spinner2

public void spinner2meth(){
Spinner spinner2 = (Spinner) findViewById(R.id.spinner2);
ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, stringArray2);
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner2.setAdapter(adapter2);
spinner2.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onNothingSelected(AdapterView<?> parent) {
}

@Override
public void onItemSelected(final AdapterView<?> parent,
View view, final int pos1, long id) {
// your code after selecting state in second spinner
}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}

9 comments:

  1. I'm having a nullpointerexception while following this code. can you please help me with this?

    ReplyDelete
    Replies
    1. What output you get when you run the web service in the Browser?

      Delete
    2. int intPropertyCount = response.getPropertyCount();
      list= new String[intPropertyCount];

      for (int i = 0; i < intPropertyCount; i++)
      {
      list[i] = response.getPropertyAsString(i).toString();
      }



      add this code in try statement. and in spinner method instead of stringarray use list. declare list as global variable.

      Delete
    3. or check this post http://andygeeks.blogspot.in/2014/02/using-string-array-as-response-from-net.html

      Delete
  2. <
    ArrayOfAnyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
    <
    anyType xsi:type="xsd:string">NCR
    <
    anyType xsi:type="xsd:string">CAR
    <
    anyType xsi:type="xsd:string">REGION I
    <
    anyType xsi:type="xsd:string">REGION II
    <
    anyType xsi:type="xsd:string">REGION III
    <
    anyType xsi:type="xsd:string">REGION IV-A
    <
    anyType xsi:type="xsd:string">REGION IV-B
    <
    anyType xsi:type="xsd:string">REGION V
    <
    anyType xsi:type="xsd:string">REGION VI
    <
    anyType xsi:type="xsd:string">REGION VII
    <
    anyType xsi:type="xsd:string">REGION VIII
    <
    anyType xsi:type="xsd:string">REGION IX
    <
    anyType xsi:type="xsd:string">REGION X
    <
    anyType xsi:type="xsd:string">REGION XI
    <
    anyType xsi:type="xsd:string">REGION XII
    <
    anyType xsi:type="xsd:string">REGION XIII
    <
    anyType xsi:type="xsd:string">ARMM
    <
    /ArrayOfAnyType>

    here is the XML output of my webservice..

    I just placed a space on every letter "a" after the open bracket because it just give out NCR, REGION 1, so on and so forth.

    ReplyDelete
    Replies
    1. Fine you are getting the response. Check the 2nd reply you wil get the result. Or the other post. Your web response is string array not object so no need of been class.

      Delete
  3. Hi Yashwant,

    Thanks for sharing your knowledge, I have one request to you can you share your web service code.

    ReplyDelete
    Replies
    1. Hi Dhiraj, sorry for late reply. Actually after that post I've changed my code into json type and the code is in .net. If you still need it here it is


      public DataTable FillDataTableByQueryString(string sQuery)
      {
      DataTable dtblCollection = new DataTable();

      try
      {
      adpCollection = new SqlDataAdapter(sQuery, conCollection);
      adpCollection.SelectCommand.CommandType = CommandType.Text;
      adpCollection.SelectCommand.CommandTimeout = 500000;
      adpCollection.Fill(dtblCollection);
      }
      catch (Exception ex)
      {
      throw ex;
      }

      return dtblCollection;
      }




      public string GetCountryNameDetails(string sDistrict)
      {
      SQLHelper objHelper = new SQLHelper();
      DataTable dtblDetails = new DataTable();
      string sQuery = string.Empty;
      String json = String.Empty;

      try
      {
      sQuery = "SELECT DISTINCT COUNTRY FROM TableName";

      objHelper.CreateConnection("Connect");
      dtblDetails = objHelper.FillDataTableByQueryString(sQuery);

      json = Newtonsoft.Json.JsonConvert.SerializeObject(dtblDetails);
      }
      catch (Exception ex)
      {
      json = ex.Message.ToString();
      }
      finally
      {
      objHelper = null;
      dtblDetails = null;
      }

      return json;
      }

      Delete
  4. I want your web services and database to run the application

    final String SOAP_ACTION = "http://tempuri.org/GetCountryDetails";
    final String METHOD_NAME = "GetCountryDetails";
    final String NAMESPACE = "http://tempuri.org/";
    final String URL = "http://192.168.1.1/test/service.asmx";


    final String NAMESPACE = "http://tempuri.org/";
    final String URL = "http://192.168.1.1/test/service.asmx";
    final String SOAP_ACTION = "http://tempuri.org/GetStateDetails";
    final String METHOD_NAME = "GetStateDetails";

    ReplyDelete