Android m5 rc15 and Web services
Posted by blogmeister on
March 14, 2008
Currently Google’s Android is under version m5 rc15. Instead of dabbling on converting all my java applet games to possibly android’s format, I focused on checking if Android is capable of calling web services or not. The answer is no. Android’s API doesn’t contain classes that support this capability.
However, a 3rd party library called KSoap2 is available for use. From their sourceforge website, “kSOAP is a SOAP web service client library for constrained Java environments such as Applets or J2ME applications (CLDC / CDC / MIDP)”. And how lucky that Android uses Java as its developmental language.
I am not sure if it is possible to build an Android application and call a remote web service by compiling it using a builder app like Ant. Most posts in the mailing list do cover making it work using the Eclipse IDE, as does most of Android’s tutorial focuses on.
I kept swarming the net looking for possible ways and solutions with using just Ant and not an IDE as i abhor using it. In the end, I had no choice but to use Eclipse to be able to at least verify that the sample code and solution provided by someone in the mailing list does indeed work.
Download the KSoap2 library. Extract the jar file library and add it in your Eclipse project. Create a lib folder and import the jar file there. Next, right click the project name and select properties. Under the Java Build Path, add the KSoap2 jar so that it will be included in the classpath during compilation and deployment. Click OK.
The following 2 files are needed for web service communication
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.httpclient.HostConfiguration; import org.apache.commons.httpclient.HttpConnection; import org.apache.commons.httpclient.HttpConnectionManager; import org.apache.commons.httpclient.HttpState; import org.apache.commons.httpclient.HttpURL; import org.apache.commons.httpclient.SimpleHttpConnectionManager; import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.ksoap2.transport.ServiceConnection; /** * Connection using apache HttpComponent */ public class AndroidServiceConnection implements ServiceConnection { private static HttpConnectionManager connectionManager = new SimpleHttpConnectionManager(); private HttpConnection connection; private PostMethod postMethod; private java.io.ByteArrayOutputStream bufferStream = null; /** * Constructor taking the url to the endpoint for this soap communication * @param url the url to open the connection to. */ public AndroidServiceConnection(String url) throws IOException { HttpURL httpURL = new HttpURL(url); HostConfiguration host = new HostConfiguration(); host.setHost(httpURL.getHost(), httpURL.getPort()); connection = connectionManager.getConnection(host); postMethod = new PostMethod(url); } public void connect() throws IOException { if (!connection.isOpen()) { connection.open(); } } public void disconnect() { connection.releaseConnection(); } public void setRequestProperty(String name, String value) { postMethod.setRequestHeader(name, value); } public void setRequestMethod(String requestMethod) throws IOException { if (!requestMethod.toLowerCase().equals("post")) { throw(new IOException("Only POST method is supported")); } } public OutputStream openOutputStream() throws IOException { bufferStream = new java.io.ByteArrayOutputStream(); return bufferStream; } public InputStream openInputStream() throws IOException { RequestEntity re = new ByteArrayRequestEntity(bufferStream.toByteArray()); postMethod.setRequestEntity(re); postMethod.execute(new HttpState(), connection); return postMethod.getResponseBodyAsStream(); } public InputStream getErrorStream() { return null; } } AndroidHttpTransport.java import java.io.*; import org.ksoap2.transport.*; import org.ksoap2.*; import org.xmlpull.v1.*; /** * Apache HttpComponent based HttpTransport layer. */ public class AndroidHttpTransport extends Transport { String response; /** * Creates instance of HttpTransport with set url * * @param url * the destination to POST SOAP data */ public AndroidHttpTransport(String url) { super(url); } /** * set the desired soapAction header field * * @param soapAction * the desired soapAction * @param envelope * the envelope containing the information for the soap call. */ public void call(String soapAction, SoapEnvelope envelope) throws IOException, XmlPullParserException { if (soapAction == null) soapAction = "\"\""; byte[] requestData = createRequestData(envelope); requestDump = debug ? new String(requestData) : null; responseDump = null; ServiceConnection connection = getServiceConnection(); connection.connect(); try { connection.setRequestProperty("User-Agent", "kSOAP/2.0"); connection.setRequestProperty("SOAPAction", soapAction); connection.setRequestProperty("Content-Type", "text/xml"); connection.setRequestProperty("Connection", "close"); connection.setRequestProperty("Content-Length", "" + requestData.length); connection.setRequestMethod("POST"); OutputStream os = connection.openOutputStream(); os.write(requestData, 0, requestData.length); os.flush(); os.close(); requestData = null; InputStream is; try { is = connection.openInputStream(); } catch (IOException e) { is = connection.getErrorStream(); if (is == null) { connection.disconnect(); throw (e); } } //if (debug) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buf = new byte[256]; while (true) { int rd = is.read(buf, 0, 256); if (rd == -1) break; bos.write(buf, 0, rd); } bos.flush(); buf = bos.toByteArray(); responseDump = new String(buf); is.close(); is = new ByteArrayInputStream(buf); if (debug) { System.out.println("DBG:request:" + requestDump); System.out.println("DBG:response:" + responseDump); } //} parseResponse(envelope, is); System.out.println("----------------><"+envelope+"><<<"); System.out.println("|---------------->["+envelope.bodyIn +"]<<<"); System.out.println("DBG:request:" + requestDump); System.out.println("DBG:response:" + responseDump); } finally { connection.disconnect(); } } protected ServiceConnection getServiceConnection() throws IOException { return new AndroidServiceConnection(url); } } Those are the two main classes that are vital for web service communication. This last code here will be your client Android app that will connect to the web service. <pre lang="java"> private static final String SOAP_ACTION = "method"; private static final String METHOD_NAME = "method private static final String NAMESPACE = "namespace"; private static final String URL = "http://url/pathto/service/namespace"; public static String mymethod() { SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); request.addProperty("whatever_name", "whatever_value"); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.setOutputSoapObject(request); AndroidHttpTransport androidHttpTransport = new AndroidHttpTransport(URL); try { androidHttpTransport.call(SOAP_ACTION, envelope); } catch (Exception e) { e.printStackTrace(); } } |
The Android app code is pretty self explanatory. Just fill in the your values to the pre-defined variables. The request.addProperty() method is where you place your parameters in case the webservice method you want to call needs parameters supplied to it.
Requests will still be passed as XML. I hope this can help those who would want their Android apps to call webservices. I pretty had was stuck with this for probably a week browsing through the web, mailing lists or anything that I could come upon that would give me a hint as to how to make this work.
These codes were from someone in a mailing list who posted a solution. But I modified parts of it because they didn’t work in my case. Hit the run in the RUN menu of Eclipse to deploy your Android app. If you wish to see the System.out.println() messages in the console, run logcat. You won’t see those messages in the Eclipse console.










