在 android 应用程序中使用 ksoap 从 asp.net 网络服务中消耗对象列表

consuming list of object from asp.net webservice using ksoap in android app

我陷入了一种情况,我必须使用一个 asp.net 网络服务,returns 我的 android 应用程序中的一个对象列表 有问题的网络服务 returns programmedflights 列表,其中包含 flightCode,flightDate,flightType 等参数,下面是我在浏览器

中调用网络服务时从网络服务获得的 xml 结果

我希望我的应用能够读取上面的 programmedflights 并将它们设置为新的 programmedflights 对象,因为 class 在我下面的 android 应用中android app

programmedflights 的 class
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;
    }


}

这是我第一次在 android 中使用 ksoap,我完全没有任何可能的解决方案,我在网上检查了各种 post 如何完成这个但是 none是我所期望的,任何帮助将不胜感激

这也是我用来使用服务的代码

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();
        }
    } 

在与这个问题斗争了一个星期后,我终于找到了正确的方法,在对这个主题进行了大量研究之后,我发现大多数 post 关于从 dotnet web 对象列表的消费android 应用程序中的服务都遗漏了这样做的一个重要方面,主要是因为 post 没有更新 现在回到我的问题

从 android 调用网络服务意味着您正在启动一项可能需要时间才能给出结果的任务,因为该应用程序必须与服务器通信然后接收响应,要正确执行此操作,您必须实现线程,这意味着在应用程序正常运行时在后台执行任务,等待在 android 中执行此操作的响应,您必须使用 AsyncTaskService 类 但是对于我们的网络服务我将专注于 AsyncTask

所以要正确解决上面的问题,我们必须首先创建一个实现 KvmSerialisationprogrammedFlights class,因为我们的 Web 服务 return 是一个 [=16] 的列表=] 我们需要在 SoapEnvelope 中发送序列化 class 的对象,以帮助服务器识别并正确映射我们的对象属性,以便接收我们想要的正确响应,以了解有关 ksoap2 的更多信息KvmSerialisation 访问此 link

下面是我们的 programmedFlights class 实现 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 + '\'' +
                '}';
    }
}

在创建我们的序列化后 class 现在这是我们的主要 activity 和我们将用来调用我们的网络服务的私有 AsyncTask class 和 return 我们的对象

对象将 return 放入列表中,我们将在 TextView 中显示其中一个对象,长度为列表

//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);
        }
    }

 }

注意:切勿直接从 doinBackground 获取 WebMethod 响应,这将导致空响应,并且 java.io.IOException 始终使用 onPostExecute 得到你的回应,就像我上面用这条线所做的那样

final AsyncTask<Object, Void, Object> execute = new mycall().execute((Object) null);

onPostExecute 方法中,您告诉 activity 在 doinBackground 在后台执行并 return 对 onPostExecute

我希望这能帮助那些在 android 上遇到此类网络服务问题的人, post 有什么不明白的可以评论,我会回来简单解释一下