Wednesday, May 11, 2011

JSON-RPC from Android

There is a dearth of utilities on the Internetz that describe how to make a JSON-RPC 2.0 call from an Android device to a server somewhere. Attempts to create handy classes and posts on StackOverflow never quite seemed to do the trick. So... here it is. No fanfare.

Suppose you want to send this JSON string using HTTP using Content-type: application/json
{"jsonrpc":"2.0","method":"myMethod","params":[{"first":"A","second":"B"}],"id":"0"}

What makes this different from a regular HTTP call is the presence of an attachment and the Content-type: application/json designation. Here is the POST method:

 public HttpResponse doPost() throws JSONException, ClientProtocolException, IOException {
  HttpClient client = new DefaultHttpClient();
  
  JSONObject json = createMethodCall("myMethod", createMethodParams());
  Log.d(LOGTAG, json.toString());
    
  HttpResponse response = client.execute(createRequest(json));
  return response;
 }

I use the org.json libaries to construct my JSON object because the toString() method produces syntactically-correct JSON with no effort on my part:

 public JSONObject createMethodCall(String method, JSONArray params) throws JSONException {
  JSONObject json = new JSONObject();
  
  json.put("jsonrpc", "2.0");
  json.put("id", "0");   // we don't really use this so value is always zero
  json.put("method", method);
  json.put("params", params);

  return json;
 }
 
 public JSONArray createMethodParams() throws JSONException {
  JSONArray params = new JSONArray();
  
  // Default params that appear in all method calls
  params.put(new JSONObject().put("first", "A"));
  params.put(new JSONObject().put("second", "B"));
  
  // To add custom parameters, add to the return value rather than here, or this method becomes messy
  return params;
 }

The final trick is that HttpEntity is the Java object for MIME attachments. Therefore, attaching the JSON string as a StringEntity and declaring the content type as "application/json" is required for the server to recognize it as a valid JSON-RPC call.

 public HttpPost createRequest (JSONObject json) throws UnsupportedEncodingException {
  HttpPost request = new HttpPost(this.server + this.url);

  StringEntity entity = new StringEntity(json.toString());
  request.setEntity(entity);
  request.setHeader("Accept", "application/json");
  request.setHeader("Content-type", "application/json");
  
  return request;
 }

I suppose I could have gotten fancy and created a library that packages JSON-RPC more cleanly, but I chose to organize it as a collection of convenience methods. Here is the call from the parent code:

 RemoteCall remote = new RemoteCall();
 String response = null;
 try {
  response = remote.doPost();
 } catch (Exception e) {
  e.printStackTrace();
 }

3 comments:

  1. yeah this tutorial is helpful but could you post the complete code? am a beginner and it's really hard to understand

    ReplyDelete
  2. Hello,
    thanks for great tutorial. Dont you have any ideas, how to perform block call (stop request during execution)?

    ReplyDelete
  3. nice tutorial..can you provide its android source..
    abyuthup@gmail.com

    ReplyDelete