<documentIds> <string>string</string> <string>string</string> </documentIds> <pluginType>string</pluginType> <xmlConfiguration>string</xmlConfiguration>
You have to extend Vector an implement KvmSerializable. see also http://www.blackberry-forum.de/cgi-bin/YaBB.pl?num=1260616413
We want to generate this XML in the Request
<documentIds> <string>string</string> <string>string</string> </documentIds> <pluginType>string</pluginType> <xmlConfiguration>string</xmlConfiguration>
As you see, we want to generate an array with the Propertyname "documentIds" which contains strings with the propertyname "string", and to other simple string properties called "pluginType" and "xmlConfiguration".
For this you have to generate a class like this:
import java.util.Hashtable; import java.util.Vector; import org.ksoap2.serialization.KvmSerializable; import org.ksoap2.serialization.PropertyInfo; public class DocumentIDs extends Vector<String> implements KvmSerializable { private static final long serialVersionUID = -1166006770093411055L; @Override public Object getProperty(int arg0) { return this.get(arg0); } @Override public int getPropertyCount() { return 1; } @Override public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) { arg2.name = "string"; arg2.type = PropertyInfo.STRING_CLASS; } @Override public void setProperty(int arg0, Object arg1) { this.add(arg1.toString()); } }
To build the request you have to do this:
Make a new Vector-Object from this class:
DocumentIDs documentIdVector = new DocumentIDs();
then you can add elements:
documentIdVector.add("any String");
then you create a PropertyInfo with it:
documentIdsPropertyInfo = new PropertyInfo(); documentIdsPropertyInfo.setName("documentIds"); documentIdsPropertyInfo.setValue(documentIdVector); documentIdsPropertyInfo.setType(documentIdVector.getClass());
then you add all the properties to the request:
Request = new SoapObject(NAMESPACE, METHOD_NAME); Request.addProperty(documentIdsPropertyInfo); Request.addProperty("pluginType", "another string"); Request.addProperty("xmlConfiguration", "next string"); soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); soapEnvelope.setOutputSoapObject(Request); soapEnvelope.addMapping(NAMESPACE, "documentIds", new DocumentIDs().getClass());
When receiving a Response you simply cast the soapEnvelope.bodyIn to the class the response contains. and then access the Vector entries with an index and the values of a complex-type entry with getter-methods.
in the above case this whould be
DocumentIDs documentIdResultVector = (DocumentIDs)soapEnvelope.bodyIn; String resultString = documentIdResultVector.get(0);
Turn debugging on for your httpTransport like so
httpTransport.debug = true;
and then set a breakpoint at
httpTransport.call(soapaction, envelope);
inspect the values of
httpTransport.requestDump httpTransport.responseDump
The leading WSDL client code generator EasyWsdl[https://www.easywsdl.com/] produces code that facilitates ksoap2-android.
There is the also a less mature project [http://code.google.com/p/wsdl2ksoap/] that uses KSoap2-Android as well as a patch that enables something along these lines in upstream KSoap2 (details on http://code.google.com/p/ksoap2-android/issues/detail?id=34 however that is all I know about it..
Writing a three dimensional array (as an example) can be done with a Marshaller implemented e.g. like that, reading still needs to be done
import org.ksoap2.serialization.Marshal; import org.ksoap2.serialization.PropertyInfo; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; public class MarshallArray implements Marshal { //this method doesn't work yet public Object readInstance(XmlPullParser parser, String namespace, String name, PropertyInfo expected) throws IOException, XmlPullParserException { return parser.nextText(); } public void register(SoapSerializationEnvelope cm) { cm.addMapping(cm.xsd, "String[][][]", String[][][].class, this); } public void writeInstance(XmlSerializer writer, Object obj) throws IOException { String[][][] myArray = (String[][][]) obj; for (int i = 0; i < myArray.length; i++) { writer.startTag("", "ArrayOfArrayOfString"); for (int j = 0; j < myArray[i].length; j++) { writer.startTag("", "ArrayOfString"); for (int k = 0; k < myArray[i][j].length; k++) { writer.startTag("", "string"); writer.text(myArray[i][j][k]); writer.endTag("", "string"); } writer.endTag("", "ArrayOfString"); } writer.endTag("", "ArrayOfArrayOfString"); } } }
You can create an array of pojos by just parsing through a SoapObjects properties, which are each SoapObjects themselves. Your response returned from the webservice will be a SoapObject (unless it is very simple - SoapPrimitive then, or it failed.. SoapException then) and you can parse it manually with the various methods like getProperty, getAttribute and so on. See the javadoc for SoapObject for more.
ArrayList<Pojo> pojos = null; int totalCount = soapobject.getPropertyCount(); if (detailsTotal > 0 ) { pojos = new ArrayList<Pojo>(); for (int detailCount = 0; detailCount < totalCount; detailCount++) { SoapObject pojoSoap = (SoapObject) soapobject.getProperty(detailCount); Pojo Pojo = new Pojo(); Pojo.idNumber = pojoSoap.getProperty("idNumber").toString(); Pojo.quantity = pojoSoap.getProperty("quantity").toString(); pojos.add(Pojo); } }
To get this xml:
<users> <user> <name>Jonh</name> <age>12</age> </user> <user> <name>Marie</name> <age>27</age> </user> </users>
You would do this:
SoapObject users = new SoapObject(NAMESPACE, "users"); SoapObject john = new SoapObject(NAMESPACE, "user"); john.addProperty("name", "john"); john.addProperty("age", 12); SoapObject marie = new SoapObject(NAMESPACE, "user"); john.addProperty("name", "marie"); john.addProperty("age", 27); users.addSoapObject(john); users.addSoapObject(marie);
In a similar manner if you have an array of objects or primitives you can build a loop iterating through and adding as above. The approach above works as of 2.5.5. Prior you have to create a SoapObject and add it as a property.
Or look above to "sending/receiving array of complex types or primitives"
You can also add any required attributes to each SoapObject as necessary.
public class ConnectionWithSelfSignedCertificate { private KeyStore keyStore; public ConnectionWithSelfSignedCertificate(KeyStore keyStore) { this.keyStore = keyStore; } public void dummy(String host, int port, String file, int timeout) throws Exception { SoapObject client = new SoapObject("", "dummy"); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.bodyOut = client; HttpsTransportSE transport = new HttpsTransportSE(host, port, file, timeout); ((HttpsServiceConnectionSE) transport.getConnection()).setSSLSocketFactory(getSSLSocketFactory()); transport.call("", envelope); } private SSLSocketFactory getSSLSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(keyStore); SSLContext context = SSLContext.getInstance("SSL"); context.init(null, tmf.getTrustManagers(), null); return context.getSocketFactory(); } }
To send a byte array (e.g an image) you need to enable MarshalBase64 by adding it as a mapping to the envelope and then add the byte array as a base64 encoded array.
String path = Environment.getExternalStorageDirectory().getAbsolutePath(); String FILE = "/PdfCheck1.pdf"; String pathCompleto = path+FILE; Log.i("","Path completo : "+ pathCompleto); byte[] filefirma = convertDocToByteArray(pathCompleto); Intervento.addProperty("FileFirma",filefirma); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); new MarshalDouble().register(envelope); new MarshalBase64().register(envelope); //serialization envelope.encodingStyle = SoapEnvelope.ENC; envelope.bodyOut = request; envelope.dotNet = true; envelope.setOutputSoapObject(request); envelope.setAddAdornments(false); envelope.implicitTypes= true; // Log.i("Envelope","settata"); HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); androidHttpTransport.debug = true; Log.i("","Prima di androidHttpTransport.call "); androidHttpTransport.call(SOAP_ACTION, envelope); Log.i("","" + androidHttpTransport.requestDump); Log.i("","" + androidHttpTransport.responseDump); Log.i("call","call"); SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse(); Log.i("SoapPrimitive","Result" + resultsRequestSOAP); Log.i("GetAttribute","Count" + resultsRequestSOAP.getAttributeCount()); b = Boolean.parseBoolean(resultsRequestSOAP.toString()); Log.i("","risultato boolean Straordinario "+b); public static byte[] convertDocToByteArray(String sourcePath) throws IOException { File f = new File(sourcePath); long l = f.length(); byte [] buf = new byte[(int) l]; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { InputStream fis = new FileInputStream(sourcePath); for (int readNum; (readNum = fis.read(buf)) != -1;) { bos.write(buf, 0, readNum); Log.i("","read num bytes: "+readNum); } } catch (IOException e) { System.out.println("IO Ex"+e); } byte[] bytes = bos.toByteArray(); // for(int i = 0;i<bytes.length;i++) // { // Log.i("","bytes : "+bytes[i]); // } }
use the class HttpTransportBasicAuth from the extras package
use the jar from the ksoap2-extras-ntlm module with the NtlmTransport
Check out the Android application WCF Tester mentioned on the links:howto.html[How To] page as well as client tools like SoapUI.
If you need to use an arrays of parameters, you can use HashMap and just register MarshalHashTable object. MarshalHashTable is needed to use HashTable o bject as container of parameters:
Hashtable hashtable = new Hashtable(); hashtable.put("is_report", false); hashtable.put("r_how", 1); _client.addProperty("params",hashtable); SoapSerializationEnvelope _envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); _envelope.bodyOut = _client; HttpTransportSE _ht = new HttpTransportSE("http://www.drebedengi.ru/soap/"); _ht.debug = true; (new MarshalHashtable()).register(_envelope);
also see the discussion on the mailing list https://groups.google.com/forum/?fromgroups=#!topic/ksoap2-android/OeP-jWVLZMw
Many web services use cookies to maintain state between different calls to the web service. ksoap2-android exposes enough of the underlying HTTP headers to enable the developer to receive, save and return those cookies as needed.
Cookies as simply received from the web service and sent to the web service as headers in the HTTP preamble. In order to use cookies with the ksoap2-android, one needs to save any returned cookies and return them with subsequent calls to the web service.
The HttpTransportSE class exposes the method call that, beyond the required SOAP parameters, also accepts a List of HeaderProperty instances. It also returns a like List. This provides the ability to append additional headers to the request and review the returned headers. Since a cookie is just one of those header, one can use this facility to send and receive cookies.