Thursday, April 15, 2010

asynchronous http query for android

Surprisingly i found not as much information on it as i expected. So i had to make my own class for async requests.


Here is how it can be used:

new Service("http://localhost/list.php").query("limit=10",new android.os.Handler.Handler(), new ServiceHandler() {
public void notify(boolean success, String response) {
if (success) txtResult.setText((CharSequence)response);
}
}});



Here it is:


//ok, just a callback
public abstract interface ServiceHandler {
public abstract void notify(boolean success, String response);
}

public class Service {
private String url;
public Service(String url) {
this.url = url;
}
public void query(String rawdata,final Handler handler, final ServiceHandler serviceHandler) {
HttpClient httpClient = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), 25000);
HttpPost httpPost = new HttpPost(this.url);
try {
httpPost.setEntity(new StringEntity(rawdata));
} catch (Exception e) {
serviceHandler.notify(false, (String)null);
}

//now let's run query itself in another thread
new Thread(new ServiceRunner(httpClient,httpPost,new ServiceHandler() {
public void notify(final boolean success, final String response) {
//we've recieved response, but we need to pass it to the UI thread
handler.post(new Runnable() {
public void run() {
serviceHandler.notify(success, response);
}
});
}
})).start();
}

//this class does all dirty work: it connects, sends post data and reads response
private class ServiceRunner implements Runnable {
private HttpClient httpClient;
private HttpPost httpPost;
private ServiceHandler handler;
public ServiceRunner(HttpClient httpClient,HttpPost httpPost,ServiceHandler serviceHandler) {
this.httpClient = httpClient;
this.httpPost = httpPost;
this.handler = serviceHandler;
}
public void run() {
try {
HttpResponse response = null;
response = httpClient.execute(httpPost);
processEntity(handler, response.getEntity());
} catch (ClientProtocolException e) {
handler.notify(false, null);
} catch (IOException e) {
handler.notify(false, null);
}
}
}

//this method reads response line by line
private void processEntity(ServiceHandler handler,HttpEntity entity) throws IllegalStateException,IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
String line = "";
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) sb = sb.append(line).append("\n");
handler.notify(true, sb.toString());
}

}


If there will be at least a single person reading this post, i'll make a next post explaining how to use this class for JSON-serialized requests.