The notes taken from the Google I/O talk on “Android REST client applications“. There is a number of reasons why to implement a native REST application on a mobile device instead of using a mobile website and app in a browser. Some of the reasons:
- better integration with the content providers of the mobile platform
- access to sensors and other applications (Services, Intents, etc)
- ability to augment the functionality of the RESTful application with other applications on a device
- much better UI integration
- simply: users prefer native apps to running apps in a browser
Service API pattern
Using this pattern, we wrap all the REST interactions in a worker thread on a service.Provide a processor that interacts with a local Content Provider, and provides a local cache for the REST resources. Add two extra columns: status column and result column. Every resource has a transition state, and we need to state (STATE_POSTING, STATE_UPDATING, STATE_DELETING, STATE_OK). The result column contains the HTTP return code for the last REST operation.
Implement a ServiceHelper, singleton, that exposes a simple asynchronous public API to be used by the user interface. Prepare and send the Service request on the forward path:
- check if the method is already pending (check the state)
- create the request Intent
- add the operation type and a unique request id
- add the method specific parameters
- add the binder callback
- call startService(Intent)
- return the request id
On a return path: Dispatch callbacks to the user interface listeners
Handling REST Method in an Activity:
- onResume() add the listener
- onPause() remove the callback
- consider these cases: callback comes back when (A) activity is active (B) activity is paused, and return AFTER the callback is made (C) Activity is paused/resumed while the method was running.
- CursorAdapter handles the ContentProvider notification by implementing a ContentObserver.
For performance considerations, use these:
- Froyo uses org.json API, with much improved performance. Use it.
- Enable the gzip content encoding when possible.
- Use the Apache HTTP client (not the Java one)
- Be nice, shutdown the Service if there is no requests queued
- Implement a queue for downloads (if you need to download multiple things in parallel)
ContentProvider API pattern
Similar to the previous model, however, the Activity interacts with the ContentProvider, that works as a facade and hides all the REST Service interactions behind the scenes. It is now the ContentProvider that interacts with Service Helper.
In this pattern the retries have to be internally handled by the ContentProvider.
(Simple) ContentProvider + SyncAdapter pattern
Variant of the ContentProvider pattern. SyncAdapter helps to synchronise remote and local content. The SyncManager implements a queue of SyncAdapters, and manages system-wide syncing. SyncAdapter with the help of SyncManager. It will re-try with incremental delays upon sync failures.
This pattern may not update things as fast as the manual approaches above. (And, even though GMail and Calendar are using it, the Google Twitter Client is probably not using it, right?)
- Do not implement REST methods inside Activities
- Start long running operations from a Service
- Persist early and persist often
- Cursors can only hold of up to 1MB of data. Minimise amount of data you store in Cursor.
- Minimize network usage
- Always use paging (hopefully the REST API supports paging)
- New in Froyo: Android Cloud to Device Messaging, push notifications (will safe lots of battery life)