(or “looking at the limitations of the Android home screen widgets framework”)
A couple of years ago, I wrote a Windows Mobile app called TwitToday : a Twitter widget for the “Today screen” (the default screen when the phone is on, with all apps closed or minimised).
The rationale was that it was useful to have a way to post a tweet quickly when you don’t want to have to wait for a full-blown client to start.
Or if you don’t want to incur the battery or memory cost of leaving a client running all the time.
Android has a “Home screen”, which is similar to the Today screen on Windows Mobile. And it has support for widgets. This led several people to ask me why I never ported TwitToday to Android.
The short answer is that I did try, but the current state of the widgets framework made it impossible.
I tried to write a TwitToday widget back when the Android widgets framework was first introduced in Android 1.5.
It all started quite well:
- I wrote the Android Service that would carry out the background task of posting a tweet. No problems there – it worked fine.
- I wrote the widget XML to define the GUI. This is what you can see running in the screenshot. And it works… sort of. It has a text box that you can type up to 140 characters into. And if you press the button, it causes a chunk of code to get invoked.
The problem came when I tried to link the two together: to get the Service that posts tweets to obtain the String from the text box in my widget.
This isn’t possible. Android’s widget framework as it currently stands is geared around displaying information to the user, not collecting user input.
The API access to widgets at runtime is to go through an intermediate layer called RemoteViews – an Android mechanism that lets you implement a View within another process (in this case, the Home screen’s process).
Look at the Reference page for RemoteViews. RemoteViews only provide “setter” methods. No “getter” methods. My code can set the text in the text box (so I could display tweets that I download from twitter.com). But it can’t get it.
So after the user types in their tweet, and presses the button, my code has no way to get the String that they typed in.
I haven’t seen this explained in the Android developer docs, but I should’ve guessed from the guide to creating App Widgets:
… you must be aware that App Widget layouts are based on RemoteViews, which do not support every kind of layout or view widget.
A RemoteViews object (and, consequently, an App Widget) can support … the following widget classes:
Descendants of these classes are not supported.
You normally create editable text boxes using EditText (a subclass of TextView). As EditText wasn’t available for App Widgets, I made my own by using a TextView (which is supported) and setting the editable and cursorVisible properties to
That gave me an editable text box where a user can type tweets into. But it doesn’t change the fact that the intermediate RemoteViews API layer that I have to go through to access it, still doesn’t have a
getTextViewText method, only a
In hindsight, what the supported classes have in common are that they are all ways of displaying information, not collecting it. (With the exception of buttons which can accept button presses…. which is sort of input).
I guess EditText was left out for a reason.
It is more than a little frustrating. The guys behind Android obviously see the benefit of being able to enter text into widgets in the Home screen, as Android has a Google Search widget that does exactly that.
But, looking at the source, they cheated. They don’t use the widget framework that we lowly app developers have to use. The Search widget is part of the Home screen process itself. It’s built in, rather than having to use the external plugin API. This means it isn’t subject to the same restrictions. Spoilsports
So, for the moment, short of copying the Google Search Widget approach and coming up with my own customised version of Android OS that includes a Twitter widget, I’m not porting TwitToday to Android.