(i'm trying to say hello, but the site keeps deleting it oO)... ! Here is my question : I found out how to send a request to a webservice using ksoap, but i still cannot figure out where to add my XML to the request ! Here is my code :
public static SoapObject soap () throws IOException, XmlPullParserException {
SoapObject request = new SoapObject (NAMESPACE, METHOD_NAME);
/* HERE IS THE PROBLEM */
request.addProperty(toto, HERE IS MY XML);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope (
SoapEnvelope.VER11);
envelope.setOutputSoapObject (request);
HttpTransportSE androidHttpTransport = new HttpTransportSE (URL);
androidHttpTransport.debug = true;
androidHttpTransport.call (SOAP_ACTION, envelope);
SoapObject soapResult = (SoapObject) envelope.getResponse ();
return soapResult;
}
If i delete the "request.addProperty line", it reaches the server, but it does nothing, because i need to send my XML. If someone know how to do that, it would definitely make my day !!
Thanks you for reading this !
Maybe it doesn't help you with this particular issue, but I would not recommended using ksoap. I wasted so much time getting it to work and after that I wrote my SOAP client with few hours and it works without problem.
It's easy:
public static HashMap<String, Object> callSOAPServer(StringBuffer soap /* YOUR XML GOES HERE*/,String action) {
HashMap<String, Object> xMap = new HashMap<String, Object>();
byte[] result = null;
byte[] data = new byte[1024*1024];
HttpClient httpclient = new DefaultHttpClient(); /* Your probably need to edit client for your needs, like timeout, scheme, etc */
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DataInputStream is = null;
boolean download = true;
HttpPost httppost = new HttpPost(/* YOUR URL GOES HERE */ );
httppost.setHeader("soapaction", action);
httppost.setHeader("Content-Type", "text/xml; charset=utf-8");
try {
HttpEntity entity = new StringEntity(soap.toString(),HTTP.UTF_8);
httppost.setEntity(entity);
HttpResponse response = httpclient.execute(httppost);
HttpEntity r_entity = response.getEntity();
if (r_entity != null) {
result = new byte[(int) r_entity.getContentLength()];
size = result.length;
if (r_entity.isStreaming()) {
is = new DataInputStream(r_entity.getContent());
while((count = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, count);
total +=count;
}
}
buffer.flush();
result = buffer.toByteArray();
data = null;
buffer = null;
}
} catch (Exception e) {
e.printStackTrace();
result = null;
}
if(result !=null){
try {
String sb;
String sn;
sb = new String(result, "UTF-8");
sn = sb.replace("&", "AMP"); //Precaution for SAX parser
result = sn.getBytes();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
xMap.put(STATUS, "OK");
xMap.put(SOAP, result);
}else{
if(xMap.get(STATUS) == null) {
xMap.put(STATUS, "ERROR");
}
}
httpclient.getConnectionManager().shutdown();
return xMap;
}
Here is parser:
public ArrayList< HashMap<String,String>> parseSoap (byte[] soapResult,String soapFunctionName, String... args) {
ArrayList< HashMap<String,String>> xMap = new ArrayList< HashMap<String,String>>();
if(soapResult == null) xMap.put(STATUS, "Where is stuff to handle");
byte[] initReqrepsonse = soapResult;
ByteArrayInputStream bais = new ByteArrayInputStream(initReqrepsonse);
SAXParserFactory spf = SAXParserFactory.newInstance();
try {
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
if(soapFunctionName.equals(NEWS)) { /*IF YOU USE MULTIPLE SOAP FUNCTION, YOU NEED TO DETERMINE WHICH IS WHICH...*/
NewsXMLHandler myXMLHandler = new NewsXMLHandler(); /*..BECAUSE HERE YOU NEED TO SPECIFY FIELDS WHICH YOU WANT TO RETRIEVE FROM XML*/
xr.setContentHandler(myXMLHandler);
xr.parse(new InputSource(bais));
xMap.put(SOAP_OUTPUT, myXMLHandler.getOutput());
myXMLHandler = null;
}
sp = null;
xr = null;
} catch (Exception e) {
e.printStackTrace();
}
spf = null;
return xMap;
}
And for that thing (NewsXMLHandler) which determines which fields you want to parse:
public class NewsXMLHandler extends DefaultHandler {
public NewsXMLHandler() {}
private ArrayList< HashMap<String,String> > data;
private HashMap<String,String> dataHash;
private final StringBuilder mStringBuilder = new StringBuilder();
private boolean bStore = false;
ArrayList< HashMap<String,String>> getOutput() {
return data;
}
@Override
public void startDocument() throws SAXException
{
data = new ArrayList< HashMap<String,String> >();
}
@Override
public void endDocument() throws SAXException
{
}
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
mStringBuilder.setLength(0);
bStore = true;
try {
//HERE YOU NEED TO SPECIFY WHICH IS ROOT NODE OF XML FROM SOAP, IN MY EXPERIENCE ITS OUT
if(localName.equalsIgnoreCase("out")) {
dataHash = new HashMap<String,String>();
}
} catch (Exception e)
{
Log.d("error in startElement", e.getStackTrace().toString());
}
}
@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException
{
bStore = false;
//HERE IT IS, JUST WRITE NAME OF NODE WHICH YOU WANT TO USE FOR YOUR APPLICATION
if (localName.equalsIgnoreCase("your node name"))
{
dataHash.put("your node name", mStringBuilder.toString().trim());
}
if (localName.equalsIgnoreCase("your node name 2"))
{
dataHash.put("your node name 2", mStringBuilder.toString().trim());
}
// CONTINUE WITH THOSE IFS UNTIL YOU HAVE ALL FIELDS WHICH YOU NEED COVERED
// HERE YOU WRAP ALL OF THOSE HIGHER NODE AND SAVE TO ARRAYLIST, SO IF THERE ARE MORE OF THEM, YOU GET THEM ALL - AGAIN ITS NAME OF ROOT NODE
if(localName.equalsIgnoreCase("out")) {
data.add(dataHash);
dataHash = null;
}
}
@Override
public void characters(char ch[], int start, int length)
{
if (bStore)
{
mStringBuilder.append(ch, start, length);
if(mStringBuilder.length() == 0) mStringBuilder.setLength(0);
}
}
}
And here goes the usage. As it seems you alredy figured out, you can't execute URL request on main thread. You just need to use AsyncTask, Service, IntentService, etc. I am not going to cover it here. I like to use IntentService and save entries to database.
So lets say, you wrap those two static function in class SOAPHandler:
HashMap<String, Object> SOAPResponse = SOAPHandler.callSOAPSERVER(/*YOUR XML REQUEST HERE*/, /*NAME OF SOAP METHOD ON SERVER*/)
ArrayList< HashMap<String,String>> parsedEntries = SOAPHandler.parseSoap(SOAPResponse, NEWS, NULL);
foreach(HashMap<String,String> hash : parsedEntries) {
String entryOne = hash.get("your node name");
String entryTwo = hash.get("your node name 2");
//HERE YOU HAVE YOUR STRINGS, DO WHATEVER WITH THEM
}