i am stuck in asituation where i have to consume an asp.net webservice that returns a list of objects in my android app the webservice in question returns a list of programmedflights
which contains parameters like flightCode,flightDate,flightType
and the like, below is the xml result i get from the webservice when i call it in my browser
i want my app to be able to read the programmedflights
as above and set them as new programmedflights
objects as the class is in my android app below is my class of programmedflights
in android app
public class programmed_flights {
private int id;
private String company;
private String flight_date;
private String flight_num;
private String air_port;
private String flight_type;
private String status;
public programmed_flights(){
}
public programmed_flights(String company, String flight_date, String flight_num, String air_port,String flight_type,String status ) {
this.company = company;
this.flight_date = flight_date;
this.flight_num = flight_num;
this.air_port = air_port;
this.flight_type = flight_type;
this.status = status;
}
public String flightToString() {
return company+" "+flight_date+" "+flight_num+" "+air_port+" "+flight_type+" "+status;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getFlight_date() {
return flight_date;
}
public void setFlight_date(String flight_date) {
this.flight_date = flight_date;
}
public String getFlight_num() {
return flight_num;
}
public void setFlight_num(String flight_num) {
this.flight_num = flight_num;
}
public String getAir_port() {
return air_port;
}
public void setAir_port(String air_port) {
this.air_port = air_port;
}
public String getFlight_type() {
return flight_type;
}
public void setFlight_type(String flight_type) {
this.flight_type = flight_type;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
it my first time using ksoap in android an i am totally void of any possible solution to this, i checked various post online on how to get this done but none was what i expected, any help will be greatly apreciated
also this is the code i use to consume the service
public String getSoap(long option, String dt){
SoapObject request = new SoapObject(WSDL_TARGET_NAMESPACE,OPERATION_NAME);
PropertyInfo opt=new PropertyInfo();
opt.setName("option");
opt.setValue(option);
opt.setType(long.class);
request.addProperty(opt);
PropertyInfo date=new PropertyInfo();
date.setName("dt");
date.setValue(dt);
date.setType(String.class);
request.addProperty(date);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE httpTransport = new HttpTransportSE(SOAP_ADDRESS);
Object response=null;
try
{
httpTransport.call(SOAP_ACTION, envelope);
response = envelope.getResponse();
}
catch (Exception exception)
{
exception.printStackTrace();
response=exception.toString();
}
return response.toString();
}
}
After fighting with this trouble for one week i finally found the right way of doing this, after doing much research about the subject i found out that most post regarding the consumption of list of object from dotnet web services in android application all left out an important aspect of doing that mainly because the post are not updated now back to my issue
calling a webservice from android means you are initiating a task that probably takes time to give a result since the app has to communicate with the server and then recieve a response, to do this correctly you have to implement threading which means doing a task in background while the app runs normally waiting for a response to do this in android you have to user the AsyncTask
or Service
Classes but for our web service i will forcus on AsyncTask
so to solve the problem above correctly we have to first create a programmedFlights
class that implement KvmSerialisation
since our web service returns a list of programmedFlights
objects we need to send that serialised class in our SoapEnvelope
to help the server identify an do a correct mapping of our objects properties so as to recieve the correct response we want ,to know more about ksoap2 KvmSerialisation
visit this link
below is our programmedFlights
class tha implements KvmSerialasation
package com.YouPakageName.serialisation;
//importing needed classes
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;
import java.util.Hashtable;
public class programmedFlights implements KvmSerializable {
//setting properties
public int id;
public String company;
public String flight_date;
public String flight_num;
public String flight_type;
public String air_port;
public String status;
//default constructor
public programmedFlights(){
}
//constructor with parameters
public programmedFlights(int id,String company,String flight_date,String flight_num,String flight_type,String air_port,String status){
this.id = id;
this.company = company;
this.flight_date = flight_date;
this.flight_num = flight_num;
this.flight_type = flight_type;
this.air_port = air_port;
this.status = status;
}
//here we override our kvmSerialisation methods an adapt to our class
//needed method
@Override
public Object getProperty(int index) {
switch(index)
{
case 0:
return id;
case 1:
return company;
case 2:
return flight_date;
case 3:
return flight_num;
case 4:
return flight_type;
case 5:
return air_port;
case 6:
return status;
}
return null;
}
//needed method
//here just return the sum of properties in the class
@Override
public int getPropertyCount() {
return 7;
}
//needed method
@Override
public void setProperty(int index, Object value) {
switch(index)
{
case 0:
id = Integer.parseInt(value.toString());
break;
case 1:
company = value.toString();
break;
case 2:
flight_date = value.toString();
break;
case 3:
flight_num = value.toString();
break;
case 4:
flight_type = value.toString();
break;
case 5:
air_port = value.toString();
break;
case 6:
status = value.toString();
break;
default:
break;
}
}
//needed method
@Override
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
switch(index)
{
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "id";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "company";
break;
case 2:
info.type = PropertyInfo.STRING_CLASS;
info.name = "flight_date";
break;
case 3:
info.type = PropertyInfo.STRING_CLASS;
info.name = "flight_num";
break;
case 4:
info.type = PropertyInfo.STRING_CLASS;
info.name = "flight_type";
break;
case 5:
info.type = PropertyInfo.STRING_CLASS;
info.name = "air_port";
break;
case 6:
info.type = PropertyInfo.STRING_CLASS;
info.name = "status";
break;
default:break;
}
}
//just a method to present our class in String form
//not actually needed
@Override
public String toString() {
return "flightPrograms{" +
"id=" + id +
", company='" + company + '\'' +
", flight_date='" + flight_date + '\'' +
", flight_num='" + flight_num + '\'' +
", flight_type='" + flight_type + '\'' +
", air_port='" + air_port + '\'' +
", status='" + status + '\'' +
'}';
}
}
after creating our serialisation class now this is our main activity with a private AsyncTask
class that we will use to call our web service and return our objects
the objects will be returned in a list and we will display one of them in a TextView with the length of the list
//importing needed classes
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpResponseException;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import android.widget.TextView;
public class test_db extends FragmentActivity implements AdapterView.OnItemSelectedListener{
TextView tdate = null;
//variables needed to call our web service
private final String SOAP_ACTION = "http://yourOwnNAMESPACE.org/getTodayFlights";
private final String OPERATION_NAME = "getTodayFlights";
private final String WSDL_TARGET_NAMESPACE = "http://yourOwnNAMESPACE/";
private final String SOAP_ADDRESS = "http://www.yourServiceHost/WebServicePage.asmx";
//holds the recieved list of objects
public programmedFlights[] list;
//property we send to WebMethod
Long getnet = Long.valueOf(1);
//method for looping into response to get out objects (deserialisation)
public static programmedFlights[] RetrieveFromSoap(SoapObject response)
{
programmedFlights[] flights = new programmedFlights[response.getPropertyCount()];
for (int i = 0; i < flights.length; i++) {
SoapObject obj = (SoapObject)response.getProperty(i);
programmedFlights flyer = new programmedFlights();
flyer.id = Integer.parseInt(obj.getProperty(0).toString());
flyer.company = obj.getProperty(1).toString();
flyer.flight_date = obj.getProperty(2).toString();
flyer.flight_num = obj.getProperty(3).toString();
flyer.flight_type = obj.getProperty(4).toString();
flyer.air_port = obj.getProperty(5).toString();
flyer.status = obj.getProperty(6).toString();
flights[i] = flyer;
}
return flights;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_db);
//setting our TextView
tdate = findViewById(R.id.textView6);
//calling the AsyncTask to execute our Wedservice in doinBackground
final AsyncTask<Object, Void, Object> execute = new mycall().execute((Object) null);
}
private class mycall extends AsyncTask<Object,Void,Object>{
@Override
protected Object doInBackground(Object... objects) {
SoapObject request = new SoapObject(WSDL_TARGET_NAMESPACE, OPERATION_NAME);
//setting request properties
PropertyInfo opt = new PropertyInfo();
opt.setName("option");
opt.setValue(getnet);
opt.setType(long.class);
request.addProperty(opt);
//creating our envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
//this part is important for getting our list of objects, never forget to add
//it to the envelope ******
envelope.addMapping(WSDL_TARGET_NAMESPACE, "programmedFlights", new programmedFlights().getClass());
Log.e("request",request.toString());
HttpTransportSE httpTransport = new HttpTransportSE(SOAP_ADDRESS,100000);
httpTransport.debug = true;
try {
//calling WebMethod
httpTransport.call(SOAP_ACTION, envelope);
//getting WebMethod response
SoapObject response = (SoapObject) envelope.getResponse();
//Getting our objects from soap response
list = RetrieveFromSoap(response);
//catching errors
} catch (HttpResponseException e) {
e.printStackTrace();
errors = errors+"http_response_error "+e.toString();
return errors;
} catch (SoapFault soapFault) {
soapFault.printStackTrace();
errors = errors+"soapFault_error "+soapFault.toString();
return errors;
} catch (XmlPullParserException e) {
e.printStackTrace();
errors = errors+"Xml_pull_error "+e.toString();
return errors;
} catch (IOException e) {
e.printStackTrace();
errors = errors+"I/O_error "+e.toString();
return errors;
}
return list;
}
@Override
protected void onPostExecute(Object list) {
if(list.getClass() == programmedFlights[].class ){
programmedFlights[] data = (programmedFlights[]) list;
tdate.setText(data.length+" "+data[0].toString());
tdate.append(data[1].toString());
}else if(list.getClass() == String.class){
String error = (String) list;
tdate.setText(error);
}
super.onPostExecute(list);
}
}
}
NOTE:Never get your WebMethod response from doinBackground
directly, this will result to an empty response and a java.io.IOException always use the onPostExecute
to get your response like i did above with this line
final AsyncTask<Object, Void, Object> execute = new mycall().execute((Object) null);
it in the onPostExecute
method that your tell your activity what to do with your response after doinBackground
has executed in background and returned the response to onPostExecute
i hope this will help many guys out there getting stuck on this kind of issue with webservices on android, post a comment if you don't understand something i will be back to briefly explain