Widget Tutorial

Here is a tutorial for using the DroidDraw GUI builder to build a android widget for android phones.

It builds off of the currency converter tutorial.

1) Create a layout in DroidDraw:

Steps:

  • Make the root layout RelativeLayout.
  • Drag a TextView to the upper left corner.
  • Give this TextView @+id/etod and an initial text of "Loading".
  • Drag a TextView to the lower left corner.
  • Give this id @+id/dtoe and an initial text of "".
  • Drag a button to the center on the right side.
  • Give this an id of @+id/convert and text of "Converter".
  • Press generate
  • add android:background='@drawable/appwidget_bg' to the top level RelativeLayout.
  • You can find this image here. Copy it into res/drawable/ in your eclipse project.

Yes, I realize this is wonky, part of the motivation for this tutorial is to improve widget
support in DroidDraw.

2) Create res/layout/widget.xml and copy the output of DroidDraw into that file.

 

3) In eclipse create a res/xml directory (right-click, new directory)

 

4) Create a res/xml/widget_description.xml in that directory with contents as follows:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dip"
    android:minHeight="72dip"
    android:initialLayout="@layout/widget"
    android:updatePeriodMillis="60000"
    />


5) Edit your AndroidManifest.xml, add: Inside the application block add:

<receiver
    android:name=".CurrencyWidget"
    android:label="Currency Widget">
  <intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
  </intent-filter>
  <meta-data
    android:name="android.appwidget.provider"
    android:resource="@xml/widget_description" />
</receiver>

<!-- Service to perform web API queries -->        
<service android:name=".CurrencyWidget$UpdateService" />

Inside the manifest block add:
    <uses-sdk android:minSdkVersion="3" />
    <uses-permission android:name="android.permission.INTERNET" />

6) Add the following class (complete code here):

Implement AppWidgetProvider:

public class CurrencyWidget extends AppWidgetProvider {
  @Override
  public void onUpdate(
    Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    // To prevent any ANR timeouts, we perform the update in a service
    context.startService(new Intent(context, UpdateService.class));
  }

  ...
  // Implement the Service for updates.
  public static class UpdateService extends Service {
    @Override
    public void onStart(Intent intent, int startId) {
      // Build the widget update for this rate
      RemoteViews updateViews = buildUpdate(this, getRate());

      // Push update for this widget to the home screen
      ComponentName thisWidget = new ComponentName(this, CurrencyWidget.class);
      AppWidgetManager manager = AppWidgetManager.getInstance(this);
      manager.updateAppWidget(thisWidget, updateViews);
    }

    public RemoteViews buildUpdate(Context context, double rate) {
      // Build an update that holds the updated widget contents
      RemoteViews updateViews =
         new RemoteViews(context.getPackageName(), R.layout.widget2);

      // Build the text for the widget
      DecimalFormat format = new DecimalFormat("##.##");
      String euroToDollar = format.format(rate);
      String dollarToEuro = format.format(1 / rate);
      updateViews.setTextViewText(R.id.etod, "Euros to Dollars: " + euroToDollar);
      updateViews.setTextViewText(R.id.dtoe, "Dollars to Euros: " + dollarToEuro);

      // Set up the button click handler
PendingIntent pendingIntent; Intent launchIntent = new Intent(Intent.ACTION_MAIN); launchIntent.setClass(context, CurrencyConverter.class); pendingIntent = PendingIntent.getActivity(context, 0, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT); updateViews.setOnClickPendingIntent(R.id.convert, pendingIntent); return updateViews; } ... }

Final Product

Compile, install and activate the widget on your homescreen, you should see something like: