Sunday, January 10, 2010

RemoteViews as hypertext document

In the previous blog entry I tried to demonstrate, how a web programming construct, the feed can be implemented using LiveFolders. In this entry, I would like to highlight another relatively obscure feature of the Android API, the RemoteViews widget and argue that RemoteViews are similar in nature to another web programming construct, the hypertext document itself.

RemoteViews is the key mechanism behind the AppWidget feature of the Android platform. There are many good introductions to AppWidgets (like this or this) so I will be short. AppWidget is a representation of an Android application on the home screen. The application can decide, what representative information it publishes on the home screen. As the screen estate is limited, the representation is obviously condensed, e.g. an application executing a long-running task can publish the progress indicator as home screen widget. The technical problem is that it is not evident, how to embed functionality (even condensed functionality) from another running application into the Launcher, the default home screen provider. If Launcher delegated the refreshing/redrawing of the views embedded from another application to that application, then malfunction of that application could disrupt the Launcher itself - something to be definitely avoided as the home screen is the last refuge of the users if something goes wrong with apps. Different platforms apply similar strategy. The idea is that the home screen application does not invoke other executables when it draws the home screen, it rather uses some sort of description of the widget UI in data format and displays that. For example that is the reason Symbian forces the programmer to implement widgets as HTML/JavaScript applications and that is the reason Android decoupled the applications from the Launcher view structure

The workhorse behind Android AppWidgets is the RemoteViews widget. RemoteViews is a parcelable data structure (so it can be sent through Android IPC) that captures an entire view structure. The creator of the RemoteViews sets up this data structure, by specifying the base layout and setting field values. This has no effect on the UI and therefore background components like services, broadcast event handlers, etc. can also do it. In fact, AppWidgets are broadcast event receivers, they process broadcasts from Launcher and respond with RemoteViews. When the RemoteViews data structure is received and deserialized, it can be applied to any ViewGroup of the UI and can therefore appear on the UI of another application. From this point of view, it works just like a hypertext document except that RemoteViews describes Android views and not general web controls.

RemoteViews is a powerful construct that can be easily used outside of the context of AppWidgets. I present now a simple Activity and a Service where the Service provides an entire formatted View (and not just the data) that can be displayed easily by the Activity. Even though this is against the Big Book of service-oriented architectures (services should provide raw data and the consumers should care about formatting), there are lot of use cases for this construct. For example the output data of the service may not be so easy to display (e.g. in case of a map application) or you would like to tie the output of the service with advertisement, logo or link to your main application (a PendingIntent in Android parlance). In this case your Service (broadcast receiver, etc.) may just return the View structure you would like the client application to display. In the web world, web widgets are formatted mini webpages to be embedded into other web pages, hence the similarity of this web technology with RemoteViews.

Click here to download the example program.

There are three points to note here.
  • Check ITimeViewService.aidl under the src/aexp/remoteview directory and see how the remote method returns a RemoteViews instance.
  • Check and see how the RemoteView is constructed and updated. To make the point of returning formatted views as opposed to raw data, I added two formatted TextViews and a ProgressBar embedded into two LinearLayouts to the view structure returned by the service.
  • Check and see how the RemoteView is applied to the view structure of that Activity. Everything under the "Get view data" button comes from the service when the RemoteViews is inflated into the view structure of the Activity.

RemoteViews has disadvantages, however. It cannot serialize any Views, e.g. it cannot serialize an EditText view. I am aware of only this article about the restrictions of views the RemoteViews can serialize/deserialize.


David Cheney said...

Seeking solution, I am wondering whether "a Service where the Service provides an entire formatted View" functions with a home screen AppWidget, or if some restrictions prevent that?

Thanks for a super post!

Gabor Paller said...

David, the machinery behind AppWidgets is the BroadcastReceiver. As it is documented at andoid.appwidget.AppWidgetProvider, AppWidgetProvider is just a convenience class that makes somewhat easier to handle widget-related broadcasts. If you have a Service that backs a Widget, your service needs to talk first to this BroaccastReceiver then the widget itself is refreshed by the events that the Home screen app and the this BroadcastReceiver exchange.

Rohan said...

Hi Gabor, I enjoyed reading your articles on remoteviews. However, when I try to download the project I cannot import it into eclipse. The folder also seems to have some extra inexplicable files. Can you please send me a working copy of the remoteviews project

Gabor Paller said...

Hi, Rohan,

The project is not an Eclipse project, it was created with the Android command-line tools (android create project ...). Probably you find the files needed for command line tools inexplicable (like build.xml). I think you should create a new project in Eclipse and use the "based on existing source" option (I haven't tried :-))

Efi MK said...

Hi Gabor,

I'm unable to download your source code. I'm getting an error from the server. Any other place where I can get it ?

Appreciate your help,

Gabor Paller said...

Hi, Efi,

I have just successfully downloaded the example program. Does the problem persist?

Efi MK said...

Back again. thanks.

Alex Lockwood said...

Thanks a lot, this was a great read. :)