Android Widget Development

Ken Baldauf

Software Engineer @ Originate

Android Widget Architecture

  • Consists of four components
    • XML layout
    • Configuration Activity (optional)
    • AppWidgetProvider
    • AppWidgetProviderInfo

Configuration Activity

Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
    appWidgetId = extras.getInt(
            AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
}
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_OK, resultValue);
finish();

AppWidgetProvider

  • Extension of BroadcastReceiver
  • Widget lifecycle events
    • onEnabled
    • onDisabled
    • onDeleted
    • onUpdate

onUpdate

@Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                         int[] appWidgetIds) {

        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                R.layout.example_widget_layout);
        remoteViews.setTextViewText(R.id.widget_text, "Demo String");

        appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
    }

RemoteViews

  • Parceable data structure
    • Capture an entire view structure
    • Encapsulate the application's permissions
  • Don't support all Android views and view methods
  • Drawn by homescreen or lockscreen that contains it

Handling User Interaction

Intent intent = new Intent(context, ExampleAppWidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
        intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.widget_text, pendingIntent);

AppWidgetProviderInfo

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="40dp"
    android:minHeight="40dp"
    android:updatePeriodMillis="1800000"
    android:initialLayout="@layout/example_widget_layout"
    android:widgetCategory="keyguard|home_screen"
    android:configure="com.example.widgets.ExampleWidgetConfigurationActivity"
    android:previewImage="@drawable/example_widget_preview"
    android:resizeMode="none" />

AndroidManifest

<receiver
    android:name=".ExampleAppWidgetProvider">
    <intent-filter >
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>

    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/example_widget_info" />
</receiver>

<activity android:name=".ExampleWidgetConfigurationActivity">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
    </intent-filter>
</activity>

Common Pitfalls

  • Config Activities don't automatically call onUpdate
  • AppWidgetProviders have a short lifecycle
    • Long running asynchronous tasks must be handled by a Service.
  • AppWidgetProviders and RemoteViews store no state
    • Use SharedPreferences to store widget data between updates
  • Automatic update interval minimum of 30 minutes
    • Must use an AlarmManager for more frequent updates

Resources

Widgets

By Kenneth Baldauf

Widgets

Introduction to Android home screen widget development

  • 722