8 <h2>In this document</h2>
10 <li><a href="#Basics">The Basics</a></li>
11 <li><a href="#Manifest">Declaring an App Widget in the Manifest</a></li>
12 <li><a href="#MetaData">Adding the AppWidgetProviderInfo Metadata</a></li>
13 <li><a href="#CreatingLayout">Creating the App Widget Layout</a></li>
14 <li><a href="#AppWidgetProvider">Using the AppWidgetProvider Class</a>
16 <li><a href="#ProviderBroadcasts">Receiving App Widget broadcast
20 <li><a href="#Configuring">Creating an App Widget Configuration
23 <li><a href="#UpdatingFromTheConfiguration">Updating the App Widget
25 the configuration Activity</a></li>
28 <li><a href="#preview">Setting a Preview Image</a></li>
29 <li><a href="#lockscreen">Enabling App Widgets on the Lockscreen
31 <li><a href="#lockscreen-sizing">Sizing guidelines</li>
34 <li><a href="#collections">Using App Widgets with Collections</a>
36 <li><a href="#collection_sample">Sample application</a></li>
37 <li><a href="#implementing_collections">Implementing app widgets with
40 <li><a href="#fresh">Keeping Collection Data Fresh</a></li>
47 <li>{@link android.appwidget.AppWidgetProvider}</li>
48 <li>{@link android.appwidget.AppWidgetProviderInfo}</li>
49 <li>{@link android.appwidget.AppWidgetManager}</li>
55 <p>App Widgets are miniature application views that can be embedded in other
57 (such as the Home screen) and receive periodic updates. These views are
59 to as Widgets in the user interface,
60 and you can publish one with an App Widget provider. An application component
62 able to hold other App Widgets is called an App Widget host. The screenshot
64 the Music App Widget.</p>
66 <img src="{@docRoot}images/appwidgets/appwidget.png" alt="" />
68 <p>This document describes how to publish an App Widget using an App Widget
71 <div class="note design">
72 <p><strong>Widget Design</strong></p>
73 <p>For information about how to design your app widget, read the <a
74 href="{@docRoot}design/patterns/widgets.html">Widgets</a> design guide.</p>
78 <h2 id="Basics">The Basics</h2>
80 <p>To create an App Widget, you need the following:</p>
83 <dt>{@link android.appwidget.AppWidgetProviderInfo} object</dt>
84 <dd>Describes the metadata for an App Widget, such as the App Widget's layout,
86 and the AppWidgetProvider class. This should be defined in XML.</dd>
87 <dt>{@link android.appwidget.AppWidgetProvider} class implementation</dt>
88 <dd>Defines the basic methods that allow you to programmatically interface
90 based on broadcast events. Through it, you will receive broadcasts when the
91 App Widget is updated,
92 enabled, disabled and deleted.</dd>
94 <dd>Defines the initial layout for the App Widget, defined in XML.</dd>
97 <p>Additionally, you can implement an App Widget configuration Activity. This is
99 {@link android.app.Activity} that launches when the user adds your App Widget
100 and allows him or her
101 to modify App Widget settings at create-time.</p>
103 <p>The following sections describe how to setup each of these components.</p>
106 <h2 id="Manifest">Declaring an App Widget in the Manifest</h2>
108 <p>First, declare the {@link android.appwidget.AppWidgetProvider} class in your
110 <code>AndroidManifest.xml</code> file. For example:</p>
112 <pre style="clear:right">
113 <receiver android:name="ExampleAppWidgetProvider" >
115 <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
117 <meta-data android:name="android.appwidget.provider"
118 android:resource="@xml/example_appwidget_info" />
122 <p>The <code><receiver></code> element requires the
123 <code>android:name</code>
124 attribute, which specifies the {@link android.appwidget.AppWidgetProvider} used
125 by the App Widget.</p>
127 <p>The <code><intent-filter></code> element must include an
128 <code><action></code>
129 element with the <code>android:name</code> attribute. This attribute specifies
130 that the {@link android.appwidget.AppWidgetProvider} accepts the {@link
131 android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE
132 ACTION_APPWIDGET_UPDATE} broadcast.
133 This is the only broadcast that you must explicitly declare. The {@link
134 android.appwidget.AppWidgetManager}
135 automatically sends all other App Widget broadcasts to the AppWidgetProvider as
138 <p>The <code><meta-data></code> element specifies the
139 {@link android.appwidget.AppWidgetProviderInfo} resource and requires the
140 following attributes:</p>
142 <li><code>android:name</code> - Specifies the metadata name. Use
143 <code>android.appwidget.provider</code>
144 to identify the data as the {@link android.appwidget.AppWidgetProviderInfo}
146 <li><code>android:resource</code> - Specifies the {@link
147 android.appwidget.AppWidgetProviderInfo}
148 resource location.</li>
152 <h2 id="MetaData">Adding the AppWidgetProviderInfo Metadata</h2>
154 <p>The {@link android.appwidget.AppWidgetProviderInfo} defines the essential
155 qualities of an App Widget, such as its minimum layout dimensions, its initial
157 how often to update the App Widget, and (optionally) a configuration Activity to
158 launch at create-time.
159 Define the AppWidgetProviderInfo object in an XML resource using a single
160 <code><appwidget-provider></code> element and save it in the project's
161 <code>res/xml/</code>
167 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
168 android:minWidth="294dp"
169 android:minHeight="72dp"
170 android:updatePeriodMillis="86400000"
171 android:previewImage="@drawable/preview"
172 android:initialLayout="@layout/example_appwidget"
173 android:configure="com.example.android.ExampleAppWidgetConfigure"
174 android:resizeMode="horizontal|vertical"
175 android:widgetCategory="home_screen|keyguard"
176 android:initialKeyguardLayout="@layout/example_keyguard">
177 </appwidget-provider>
180 <p>Here's a summary of the <code><appwidget-provider></code> attributes:</p>
182 <li>The values for the <code>minWidth</code> and <code>minHeight</code>
183 attributes specify the minimum amount of space the App Widget consumes
184 <em>by default</em>. The default Home screen positions App Widgets in its
185 window based on a grid of cells that have a defined height and width. If
186 the values for an App Widget's minimum width or height don't match the
187 dimensions of the cells, then the App Widget dimensions round
188 <em>up</em> to the nearest cell size.
189 <p>See the <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size">
190 App Widget Design Guidelines</a> for more information on sizing your App
193 <p class="note"><strong>Note:</strong> To make your app widget portable
194 across devices, your app widget's minimum size should never be larger
195 than 4 x 4 cells.</p>
198 <li>The <code>minResizeWidth</code> and <code>minResizeHeight</code> attributes
199 specify the App Widget's absolute minimum size. These values should specify
200 the size below which the App Widget would be illegible or otherwise unusable.
201 Using these attributes allows the user to resize the widget to a size that
202 may be smaller than the default widget size defined by the
203 <code>minWidth</code> and <code>minHeight</code> attributes.
204 Introduced in Android 3.1.
206 <p>See the <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size">
207 App Widget Design Guidelines</a> for more information on sizing your App
211 <li>The <code>updatePeriodMillis</code> attribute defines how often the App
212 Widget framework should request an update from the {@link
213 android.appwidget.AppWidgetProvider} by calling the
214 {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()}
215 callback method. The actual update
216 is not guaranteed to occur exactly on time with this value and we suggest
217 updating as infrequently as possible—perhaps no more than once an hour to
218 conserve the battery. You might also allow the user to adjust the frequency in a
219 configuration—some people might want a stock ticker to update every 15
220 minutes, or maybe only four times a day.
221 <p class="note"><strong>Note:</strong> If the device is asleep when it
222 is time for an update
223 (as defined by <code>updatePeriodMillis</code>), then the device will
225 to perform the update. If you don't update more than once per hour, this
227 cause significant problems for the battery life. If, however, you need
229 frequently and/or you do not need to update while the device is asleep,
231 perform updates based on an alarm that will not wake the device. To do
232 so, set an alarm with
233 an Intent that your AppWidgetProvider receives, using the {@link
234 android.app.AlarmManager}.
235 Set the alarm type to either {@link
236 android.app.AlarmManager#ELAPSED_REALTIME} or
237 {@link android.app.AlarmManager#RTC}, which will only
238 deliver the alarm when the device is awake. Then set
239 <code>updatePeriodMillis</code> to
240 zero (<code>"0"</code>).</p>
242 <li>The <code>initialLayout</code> attribute points to the layout resource
244 App Widget layout.</li>
245 <li>The <code>configure</code> attribute defines the {@link
246 android.app.Activity} to launch when
247 the user adds the App Widget, in order for him or her to configure App
248 Widget properties. This is optional
249 (read <a href="#Configuring">Creating an App Widget Configuration
250 Activity</a> below).</li>
252 <li>The <code>previewImage</code> attribute specifies a preview of what the
253 app widget will look like after it's configured, which the user sees when
254 selecting the app widget. If not supplied, the user instead sees your
255 application's launcher icon. This field corresponds to the
256 <code>android:previewImage</code> attribute in the <code><receiver></code>
257 element in the <code>AndroidManifest.xml</code> file. For more discussion of
258 using <code>previewImage</code>, see <a href="#preview">Setting a Preview
259 Image</a>. Introduced in Android 3.0.</li>
261 <li>The <code>autoAdvanceViewId</code> attribute specifies the view ID of the
262 app widget subview that should be auto-advanced by the widget's host. Introduced in Android 3.0.</li>
264 <li>The <code>resizeMode</code> attribute specifies the rules by which a widget
265 can be resized. You use this attribute to make homescreen widgets
266 resizeable—horizontally, vertically, or on both axes. Users touch-hold a
267 widget to show its resize handles, then drag the horizontal and/or vertical
268 handles to change the size on the layout grid. Values for the
269 <code>resizeMode</code> attribute include "horizontal", "vertical", and "none".
270 To declare a widget as resizeable horizontally and vertically, supply the value
271 "horizontal|vertical". Introduced in Android 3.1.</li>
273 <li>The <code>widgetCategory</code> attribute declares whether your App Widget can be displayed on the home screen,
274 the lock screen (keyguard), or both. Values for this attribute include "home_screen" and "keyguard". A widget that
275 is displayed on both needs to ensure that it follows the design guidelines for both widget classes. For more
276 information, see <a href="#lockscreen">Enabling App Widgets on the Lockscreen</a>. The default value is "home_screen". Introduced in Android 4.2.
279 <li>The <code>initialKeyguardLayout</code> attribute points to the layout resource
280 that defines the lock screen App Widget layout. This works the same way as the
281 {@link android.appwidget.AppWidgetProviderInfo#initialLayout android:initialLayout},
282 in that it provides a layout that can appear immediately until your app widget is initialized and able to update
283 the layout. Introduced in Android 4.2.</li>
287 <p>See the {@link android.appwidget.AppWidgetProviderInfo} class for more
289 attributes accepted by the <code><appwidget-provider></code> element.</p>
292 <h2 id="CreatingLayout">Creating the App Widget Layout</h2>
294 <p>You must define an initial layout for your App Widget in XML and save it in
296 <code>res/layout/</code> directory. You can design your App Widget using the
298 below, but before you begin designing your App Widget, please read and
300 <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html">App Widget
304 <p>Creating the App Widget layout is simple if you're
306 href="{@docRoot}guide/topics/ui/declaring-layout.html">Layouts</a>.
307 However, you must be aware that App Widget layouts are based on {@link
308 android.widget.RemoteViews},
309 which do not support every kind of layout or view widget.</p>
311 <p>A RemoteViews object (and, consequently, an App Widget) can support the
312 following layout classes:</p>
315 <li>{@link android.widget.FrameLayout}</li>
316 <li>{@link android.widget.LinearLayout}</li>
317 <li>{@link android.widget.RelativeLayout}</li>
318 <li>{@link android.widget.GridLayout}</li>
321 <p>And the following widget classes:</p>
323 <li>{@link android.widget.AnalogClock}</li>
324 <li>{@link android.widget.Button}</li>
325 <li>{@link android.widget.Chronometer}</li>
326 <li>{@link android.widget.ImageButton}</li>
327 <li>{@link android.widget.ImageView}</li>
328 <li>{@link android.widget.ProgressBar}</li>
329 <li>{@link android.widget.TextView}</li>
330 <li>{@link android.widget.ViewFlipper}</li>
331 <li>{@link android.widget.ListView}</li>
332 <li>{@link android.widget.GridView}</li>
333 <li>{@link android.widget.StackView}</li>
334 <li>{@link android.widget.AdapterViewFlipper}</li>
337 <p>Descendants of these classes are not supported.</p>
339 <p>RemoteViews also supports {@link android.view.ViewStub}, which is an invisible, zero-sized View you can use
340 to lazily inflate layout resources at runtime.</p>
343 <h3 id="AddingMargins">Adding margins to App Widgets</h3>
345 <p>Widgets should not generally extend to screen edges and should not visually be flush with other widgets, so you should add margins on all sides around your widget frame.</p>
347 <p>As of Android 4.0, app widgets are automatically given padding between the widget frame and the app widget's bounding box to provide better alignment with other widgets and icons on the user's home screen. To take advantage of this strongly recommended behavior, set your application's <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">targetSdkVersion</a> to 14 or greater.</p>
349 <p>It's easy to write a single layout that has custom margins applied for earlier versions of the platform, and has no extra margins for Android 4.0 and greater:</p>
352 <li>Set your application's <code>targetSdkVersion</code> to 14 or greater.</li>
353 <li>Create a layout such as the one below, that references a <a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">dimension resource</a> for its margins:
357 android:layout_width="match_parent"
358 android:layout_height="match_parent"
359 <strong>android:padding="@dimen/widget_margin"></strong>
362 android:layout_width="match_parent"
363 android:layout_height="match_parent"
364 android:orientation="horizontal"
365 android:background="@drawable/my_widget_background">
367 </LinearLayout>
373 <li>Create two dimensions resources, one in <code>res/values/</code> to provide the pre-Android 4.0 custom margins, and one in <code>res/values-v14/</code> to provide no extra padding for Android 4.0 widgets:
375 <p><strong>res/values/dimens.xml</strong>:<br>
376 <pre><dimen name="widget_margin">8dp</dimen></pre></p>
378 <p><strong>res/values-v14/dimens.xml</strong>:<br>
379 <pre><dimen name="widget_margin">0dp</dimen></pre></p>
383 <p>Another option is to simply build extra margins into your <a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">nine-patch</a> background assets by default, and provide different nine-patches with no margins for API level 14 or later.</p>
386 <h2 id="AppWidgetProvider">Using the AppWidgetProvider Class</h2>
388 <div class="sidebox-wrapper">
389 <div class="sidebox">
390 <p>You must declare your AppWidgetProvider class implementation as a
392 using the <code><receiver></code> element in the AndroidManifest (see
393 <a href="#Manifest">Declaring an App Widget in the Manifest</a> above).</p>
397 <p>The {@link android.appwidget.AppWidgetProvider} class extends
398 BroadcastReceiver as a convenience
399 class to handle the App Widget broadcasts. The AppWidgetProvider receives only
400 the event broadcasts that
401 are relevant to the App Widget, such as when the App Widget is updated, deleted,
402 enabled, and disabled.
403 When these broadcast events occur, the AppWidgetProvider receives the following
408 {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()}
410 <dd>This is called to update the App Widget at intervals defined by the
411 <code>updatePeriodMillis</code>
412 attribute in the AppWidgetProviderInfo (see <a href="#MetaData">Adding the
413 AppWidgetProviderInfo Metadata</a> above). This method is also called
414 when the user adds the App Widget, so it should perform the essential setup,
415 such as define event handlers for Views and start a temporary
416 {@link android.app.Service}, if necessary. However, if you have declared a
418 Activity, <strong>this method is not called</strong> when the user adds the
420 but is called for the subsequent updates. It is the responsibility of the
421 configuration Activity to perform the first update when configuration is
423 (See <a href="#Configuring">Creating an App Widget Configuration
424 Activity</a> below.)</dd>
427 {@link android.appwidget.AppWidgetProvider#onAppWidgetOptionsChanged onAppWidgetOptionsChanged()}
430 This is called when the widget is first placed and any time the widget is resized. You can use this callback to show or hide content based on the widget's size ranges. You get the size ranges by calling {@link android.appwidget.AppWidgetManager#getAppWidgetOptions getAppWidgetOptions()}, which returns a {@link android.os.Bundle} that includes the following:<br /><br />
432 <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_WIDTH}—Contains
433 the lower bound on the current width, in dp units, of a widget instance.</li>
434 <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_HEIGHT}—Contains
435 the lower bound on the current height, in dp units, of a widget instance.</li>
436 <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_WIDTH}—Contains
437 the upper bound on the current width, in dp units, of a widget instance.</li>
438 <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_HEIGHT}—Contains
439 the upper bound on the current width, in dp units, of a widget instance.</li>
442 This callback was introduced in API Level 16 (Android 4.1). If you implement this callback, make sure that your app doesn't depend on it since it won't be called on older devices.
444 <dt>{@link android.appwidget.AppWidgetProvider#onDeleted(Context,int[])}</dt>
445 <dd>This is called every time an App Widget is deleted from the App Widget
447 <dt>{@link android.appwidget.AppWidgetProvider#onEnabled(Context)}</dt>
448 <dd>This is called when an instance the App Widget is created for the first
449 time. For example, if the user
450 adds two instances of your App Widget, this is only called the first time.
451 If you need to open a new database or perform other setup that only needs to
453 for all App Widget instances, then this is a good place to do it.</dd>
454 <dt>{@link android.appwidget.AppWidgetProvider#onDisabled(Context)}</dt>
455 <dd>This is called when the last instance of your App Widget is deleted from
457 This is where you should clean up any work done in
458 {@link android.appwidget.AppWidgetProvider#onEnabled(Context)},
459 such as delete a temporary database.</dd>
460 <dt>{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)}</dt>
461 <dd>This is called for every broadcast and before each of the above callback
463 You normally don't need to implement this method because the default
465 implementation filters all App Widget broadcasts and calls the above
466 methods as appropriate.</dd>
469 <p class="warning"><strong>Note:</strong> In Android 1.5, there is a known issue
471 <code>onDeleted()</code> method will not be called when it should be. To work
473 you can implement {@link
474 android.appwidget.AppWidgetProvider#onReceive(Context,Intent)
475 onReceive()} as described in this
477 href="http://groups.google.com/group/android-developers/msg/e405ca19df2170e2">
479 to receive the <code>onDeleted()</code> callback.
482 <p>The most important AppWidgetProvider callback is
483 {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()}
484 because it is called when
485 each App Widget is added to a host (unless you use a configuration Activity). If
486 your App Widget accepts any user interaction events, then you need to register
487 the event handlers in this callback. If your App Widget doesn't create temporary
488 files or databases, or perform other work that requires clean-up, then
489 {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()}
490 may be the only callback
491 method you need to define. For example, if you want an App Widget with a button
492 that launches an Activity when clicked, you could use the following
493 implementation of AppWidgetProvider:</p>
496 public class ExampleAppWidgetProvider extends AppWidgetProvider {
498 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
499 final int N = appWidgetIds.length;
501 // Perform this loop procedure for each App Widget that belongs to this provider
502 for (int i=0; i<N; i++) {
503 int appWidgetId = appWidgetIds[i];
505 // Create an Intent to launch ExampleActivity
506 Intent intent = new Intent(context, ExampleActivity.class);
507 PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
509 // Get the layout for the App Widget and attach an on-click listener
511 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
512 views.setOnClickPendingIntent(R.id.button, pendingIntent);
514 // Tell the AppWidgetManager to perform an update on the current app widget
515 appWidgetManager.updateAppWidget(appWidgetId, views);
521 <p>This AppWidgetProvider defines only the
523 android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()}
524 method for the purpose of
525 defining a {@link android.app.PendingIntent} that launches an {@link
526 android.app.Activity} and attaching it to the App Widget's button with {@link
527 android.widget.RemoteViews#setOnClickPendingIntent(int,PendingIntent)}. Notice
528 that it includes a loop that iterates through each entry in
529 <code>appWidgetIds</code>, which is an array of IDs that identify each App
530 Widget created by this provider. In this way, if the user creates more than one
531 instance of the App Widget, then they are all updated simultaneously. However,
532 only one <code>updatePeriodMillis</code> schedule will be managed for all
533 instances of the App Widget. For example, if the update schedule is defined to
534 be every two hours, and a second instance of the App Widget is added one hour
535 after the first one, then they will both be updated on the period defined by the
536 first one and the second update period will be ignored (they'll both be updated
537 every two hours, not every hour).</p>
539 <p class="note"><strong>Note:</strong> Because {@link
540 android.appwidget.AppWidgetProvider} is an extension of {@link
541 android.content.BroadcastReceiver}, your process is not guaranteed to keep
542 running after the callback methods return (see {@link
543 android.content.BroadcastReceiver} for information about the broadcast
544 lifecycle). If your App Widget setup process can take several seconds (perhaps
545 while performing web requests) and you require that your process continues,
546 consider starting a {@link android.app.Service} in the
547 {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()}
548 method. From within the Service, you can perform your own updates
549 to the App Widget without worrying about the AppWidgetProvider closing down due
550 to an <a href="{@docRoot}guide/practices/responsiveness.html">Application
551 Not Responding</a> (ANR) error. See the <a
552 href="http://code.google.com/p/wiktionary-android/source/browse/trunk/Wiktionary/src/com/example/android/wiktionary/WordWidget.java">Wiktionary sample's AppWidgetProvider</a> for an example of an App Widget running a {@link
553 android.app.Service}.</p>
556 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.html">ExampleAppWidgetProvider.java</a>
560 <h3 id="ProviderBroadcasts">Receiving App Widget broadcast Intents</h3>
562 <p>{@link android.appwidget.AppWidgetProvider} is just a convenience class. If
564 to receive the App Widget broadcasts directly, you can implement your own
565 {@link android.content.BroadcastReceiver} or override the
566 {@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)} callback.
567 The Intents you need to care about are as follows:</p>
569 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE}</li>
570 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DELETED}</li>
571 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_ENABLED}</li>
572 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DISABLED}</li>
573 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_OPTIONS_CHANGED}</li>
578 <h2 id="Configuring">Creating an App Widget Configuration Activity</h2>
580 <p>If you would like the user to configure settings when he or she adds a new
582 you can create an App Widget configuration Activity. This {@link
583 android.app.Activity}
584 will be automatically launched by the App Widget host and allows the user to
586 available settings for the App Widget at create-time, such as the App Widget
588 update period or other functionality settings.</p>
590 <p>The configuration Activity should be declared as a normal Activity in the
591 Android manifest file.
592 However, it will be launched by the App Widget host with the {@link
593 android.appwidget.AppWidgetManager#ACTION_APPWIDGET_CONFIGURE
594 ACTION_APPWIDGET_CONFIGURE} action,
595 so the Activity needs to accept this Intent. For example:</p>
598 <activity android:name=".ExampleAppWidgetConfigure">
600 <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
605 <p>Also, the Activity must be declared in the AppWidgetProviderInfo XML file,
607 <code>android:configure</code> attribute (see <a href="#MetaData">Adding
608 the AppWidgetProviderInfo Metadata</a> above). For example, the configuration
610 can be declared like this:</p>
613 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
615 android:configure="com.example.android.ExampleAppWidgetConfigure"
617 </appwidget-provider>
620 <p>Notice that the Activity is declared with a fully-qualified namespace,
622 it will be referenced from outside your package scope.</p>
624 <p>That's all you need to get started with a configuration Activity. Now all you
626 Activity. There are, however, two important things to remember when you
627 implement the Activity:</p>
629 <li>The App Widget host calls the configuration Activity and the configuration
630 Activity should always
631 return a result. The result should include the App Widget ID
632 passed by the Intent that launched the Activity (saved in the Intent extras
634 {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID}).</li>
636 {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()}
637 method <strong>will not be called</strong> when the App Widget
639 (the system will not send the ACTION_APPWIDGET_UPDATE broadcast when a
640 configuration Activity
641 is launched). It is the responsibility of the configuration Activity to
642 request an update from the
643 AppWidgetManager when the App Widget is first created. However,
644 {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()}
645 will be called for subsequent updates—it is only skipped
649 <p>See the code snippets in the following section for an example of how to
651 from the configuration and update the App Widget.</p>
654 <h3 id="UpdatingFromTheConfiguration">Updating the App Widget from the
655 configuration Activity</h3>
657 <p>When an App Widget uses a configuration Activity, it is the responsibility of
659 to update the App Widget when configuration is complete.
660 You can do so by requesting an update directly from the
661 {@link android.appwidget.AppWidgetManager}.</p>
663 <p>Here's a summary of the procedure to properly update the App Widget and close
664 the configuration Activity:</p>
667 <li>First, get the App Widget ID from the Intent that launched the Activity:
669 Intent intent = getIntent();
670 Bundle extras = intent.getExtras();
671 if (extras != null) {
672 mAppWidgetId = extras.getInt(
673 AppWidgetManager.EXTRA_APPWIDGET_ID,
674 AppWidgetManager.INVALID_APPWIDGET_ID);
678 <li>Perform your App Widget configuration.</li>
679 <li>When the configuration is complete, get an instance of the
680 AppWidgetManager by calling
681 {@link android.appwidget.AppWidgetManager#getInstance(Context)}:
683 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
686 <li>Update the App Widget with a {@link android.widget.RemoteViews} layout by
688 {@link android.appwidget.AppWidgetManager#updateAppWidget(int,RemoteViews)}:
690 RemoteViews views = new RemoteViews(context.getPackageName(),
691 R.layout.example_appwidget);
692 appWidgetManager.updateAppWidget(mAppWidgetId, views);
695 <li>Finally, create the return Intent, set it with the Activity result, and
696 finish the Activity:</li>
698 Intent resultValue = new Intent();
699 resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
700 setResult(RESULT_OK, resultValue);
706 <p class="note"><strong>Tip:</strong> When your configuration Activity first
708 the Activity result to RESULT_CANCELED. This way, if the user backs-out of the
710 reaching the end, the App Widget host is notified that the configuration was
712 App Widget will not be added.</p>
715 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetConfigure.html">ExampleAppWidgetConfigure.java</a>
716 sample class in ApiDemos for an example.</p>
718 <h2 id="preview">Setting a Preview Image</h2>
720 <p>Android 3.0 introduces the {@link
723 android.appwidget.AppWidgetProviderInfo#previewImage} field, which specifies a
724 preview of what the app widget looks like. This preview is shown to the user from the
725 widget picker. If this field is not supplied, the app widget's icon is used for
728 <p>This is how you specify this setting in XML:</p>
730 <pre><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
732 android:previewImage="@drawable/preview">
733 </appwidget-provider></pre>
735 <p>To help create a preview image for your app widget (to specify in the {@link
736 android.appwidget.AppWidgetProviderInfo#previewImage} field), the Android
737 emulator includes an application called "Widget Preview." To create a
738 preview image, launch this application, select the app widget for your
739 application and set it up how you'd like your preview image to appear, then save
740 it and place it in your application's drawable resources.</p>
742 <h2 id="lockscreen">Enabling App Widgets on the Lockscreen</h2>
744 <p>Android 4.2 introduces the ability for users to add widgets to the lock screen. To indicate that your app widget is available for use on the lock screen, declare the {@link android.appwidget.AppWidgetProviderInfo#widgetCategory android:widgetCategory} attribute in the XML file that specifies your {@link android.appwidget.AppWidgetProviderInfo}. This attribute supports two values: "home_screen" and "keyguard". An app widget can declare support for one or both.</p>
746 <p>By default, every app widget supports placement on the Home screen, so "home_screen" is the default value for the
747 {@link android.appwidget.AppWidgetProviderInfo#widgetCategory android:widgetCategory} attribute. If you want your app widget to be available for the lock screen, add the "keyguard" value:</p>
749 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
751 android:widgetCategory="keyguard|home_screen">
752 </appwidget-provider>
755 <p>If you declare a widget to be displayable on both keyguard (lockscreen) and home, it's likely that you'll want to customize the widget depending on where it is displayed. For example, you might create a separate layout file for keyguard vs. home. The next step is to detect the widget category at runtime and respond accordingly.
757 You can detect whether your widget is on the lockscreen or home screen by calling
758 {@link android.appwidget.AppWidgetManager#getAppWidgetOptions getAppWidgetOptions()}
759 to get the widget's options as a {@link android.os.Bundle}. The returned bundle will include the key
760 {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_HOST_CATEGORY}, whose value will be one of {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or
761 {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}. This value is determined by the host into which the widget is bound. In the {@link android.appwidget.AppWidgetProvider}, you can then check the widget's category, for example:</p>
764 AppWidgetManager appWidgetManager;
766 Bundle myOptions = appWidgetManager.getAppWidgetOptions (widgetId);
768 // Get the value of OPTION_APPWIDGET_HOST_CATEGORY
769 int category = myOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
771 // If the value is WIDGET_CATEGORY_KEYGUARD, it's a lockscreen widget
772 boolean isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
775 <p>Once you know the widget's category, you can optionally load a different base layout, set different properties, and so on. For example:</p>
778 int baseLayout = isKeyguard ? R.layout.keyguard_widget_layout : R.layout.widget_layout;
782 <p>You should also specify an initial layout for your app widget when on the lock screen with the
783 {@link android.appwidget.AppWidgetProviderInfo#initialKeyguardLayout android:initialKeyguardLayout} attribute. This works the same way as the
784 {@link android.appwidget.AppWidgetProviderInfo#initialLayout android:initialLayout}, in that it provides a layout that can appear immediately until your app widget is initialized and able to update the layout.</p>
786 <h3 id="lockscreen-sizing">Sizing guidelines</h3>
788 <p>When a widget is hosted on the lockscreen, the framework ignores the {@code minWidth}, {@code minHeight}, {@code minResizeWidth}, and {@code minResizeHeight} fields. If a widget is also a home screen widget, these parameters are still needed as they're still used on home, but they will be ignored for purposes of the lockscreen.</p>
790 <p>The width of a lockscreen widget always fills the provided space. For the height of a lockscreen widget, you have the following options:</p>
793 <li>If the widget does not mark itself as vertically resizable ({@code android:resizeMode="vertical"}), then the widget height will always be "small":
795 <li>On a phone in portrait mode, "small" is defined as the space remaining when an unlock UI is being displayed.</li>
796 <li>On tablets and landscape phones, "small" is set on a per-device basis.</li>
799 <li>If the widget marks itself as vertically resizable, then the widget height shows up as "small" on portrait phones displaying an unlock UI. In all other cases, the widget sizes to fill the available height.</li>
802 <h2 id="collections">Using App Widgets with Collections</h2>
804 <p>Android 3.0 introduces App Widgets with collections. These kinds of App
805 Widgets use the {@link android.widget.RemoteViewsService} to display collections
806 that are backed by remote data, such as from a <a
807 href="{@docRoot}guide/topics/providers/content-providers.html">content
808 provider</a>. The data provided by the {@link android.widget.RemoteViewsService}
809 is presented in the App Widget using one of the following view types, which
810 we’ll refer to as “collection views:”</p>
813 <dt>{@link android.widget.ListView}</dt>
814 <dd>A view that shows items in a
816 list. For an example, see the Gmail app widget. </dd>
817 <dt>{@link android.widget.GridView}</dt>
818 <dd>A view that shows items in
819 two-dimensional scrolling grid. For an example, see the Bookmarks app
821 <dt>{@link android.widget.StackView}</dt>
823 stacked card view (kind of like a rolodex), where the user can flick the front
824 card up/down to see the previous/next card, respectively. Examples include
825 the YouTube and Books app widgets. </dd>
826 <dt>{@link android.widget.AdapterViewFlipper}</dt>
827 <dd>An adapter-backed simple
829 android.widget.ViewAnimator} that animates between two or more views. Only one
830 child is shown at a time. </dd>
833 <p>As stated above, these collection views display collections backed by remote
834 data. This means that they use an {@link android.widget.Adapter} to bind their
835 user interface to their data. An {@link android.widget.Adapter} binds individual
836 items from a set of data into individual {@link android.view.View} objects.
837 Because these collection views are backed by adapters, the Android framework
838 must include extra architecture to support their use in app widgets. In the
839 context of an app widget, the {@link android.widget.Adapter} is replaced by a
840 {@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory},
841 which is simply a thin wrapper around the {@link android.widget.Adapter}
844 requested for a specific item in the collection, the {@link
845 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} creates
846 and returns the item for the collection as a {@link android.widget.RemoteViews}
848 In order to include a collection view in your app widget, you
849 must implement {@link android.widget.RemoteViewsService} and {@link
850 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}.</p>
852 <p> {@link android.widget.RemoteViewsService} is a service that allows a remote
853 adapter to request {@link
854 android.widget.RemoteViews} objects. {@link
855 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} is an
856 interface for an adapter between a collection view (such as {@link
857 android.widget.ListView}, {@link android.widget.GridView}, and so on) and the
858 underlying data for that view. From the <a
859 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
860 sample</a>, here is an example of the boilerplate code you use to implement
861 this service and interface:
865 public class StackWidgetService extends RemoteViewsService {
867 public RemoteViewsFactory onGetViewFactory(Intent intent) {
868 return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
872 class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
874 //... include adapter-like methods here. See the StackView Widget sample.
879 <h3 id="collection_sample">Sample application</h3>
881 <p>The code excerpts in this section are drawn from the <a
882 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
886 <img src="{@docRoot}images/appwidgets/StackWidget.png" alt="" />
889 <p>This sample consists of a stack of 10 views, which display the values
890 <code>"0!"</code> through <code>"9!"</code> The sample
891 app widget has these primary behaviors:</p>
895 <li>The user can vertically fling the top view in the
896 app widget to display the next or previous view. This is a built-in StackView
899 <li>Without any user interaction, the app widget automatically advances
901 its views in sequence, like a slide show. This is due to the setting
902 <code>android:autoAdvanceViewId="@id/stack_view"</code> in the
903 <code>res/xml/stackwidgetinfo.xml</code> file. This setting applies to the view
905 which in this case is the view ID of the stack view.</li>
907 <li>If the user touches the top view, the app widget displays the {@link
908 android.widget.Toast} message "Touched view <em>n</em>," where
909 <em>n</em> is the index (position) of the touched view. For more discussion of
910 how this is implemented, see
911 <a href="#behavior">Adding behavior to individual items</a>.</li>
914 <h3 id="implementing_collections">Implementing app widgets with collections</h3>
916 <p>To implement an App Widget with collections, you follow the same basic steps
917 you would use to implement any app widget. The following sections describe the
918 additional steps you need to perform to implement an App Widget with
921 <h4>Manifest for app widgets with collections</h4>
923 <p> In addition to the requirements listed in <a href="#Manifest">Declaring an
924 App Widget in the Manifest</a>, to make it possible for App Widgets with
925 collections to bind to your {@link android.widget.RemoteViewsService}, you must
926 declare the service in your manifest file with the permission {@link
927 android.Manifest.permission#BIND_REMOTEVIEWS}. This prevents other applications
928 from freely accessing your app widget's data. For example, when creating an App
929 Widget that uses {@link android.widget.RemoteViewsService} to populate a
930 collection view, the manifest entry may look like this:</p>
932 <pre><service android:name="MyWidgetService"
934 android:permission="android.permission.BIND_REMOTEVIEWS" /></pre>
936 <p>The line <code>android:name="MyWidgetService"</code>
937 refers to your subclass of {@link android.widget.RemoteViewsService}. </p>
939 <h4>Layout for app widgets with collections</h4>
941 <p>The main requirement for your app widget layout XML file is that it
942 include one of the collection views: {@link android.widget.ListView},
943 {@link android.widget.GridView}, {@link android.widget.StackView}, or
944 {@link android.widget.AdapterViewFlipper}. Here is the
945 <code>widget_layout.xml</code> for
946 the <a href="{@docRoot}resources/samples/StackWidget/index.html">StackView
947 Widget sample</a>:</p>
949 <pre><?xml version="1.0" encoding="utf-8"?>
951 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
952 android:layout_width="match_parent"
953 android:layout_height="match_parent">
954 <StackView xmlns:android="http://schemas.android.com/apk/res/android"
955 android:id="@+id/stack_view"
956 android:layout_width="match_parent"
957 android:layout_height="match_parent"
958 android:gravity="center"
959 android:loopViews="true" />
960 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
961 android:id="@+id/empty_view"
962 android:layout_width="match_parent"
963 android:layout_height="match_parent"
964 android:gravity="center"
965 android:background="@drawable/widget_item_background"
966 android:textColor="#ffffff"
967 android:textStyle="bold"
968 android:text="@string/empty_view_text"
969 android:textSize="20sp" />
970 </FrameLayout></pre>
972 <p> Note that empty views must be siblings of the collection view for which the
973 empty view represents empty state. </p>
975 <p>In addition to the layout file for your entire app widget, you must create
976 another layout file that defines the layout for each item in the collection (for
977 example, a layout for each book in a collection of books). For example, the <a
978 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
979 sample</a> only has one layout file, <code>widget_item.xml</code>, since all
980 items use the same layout. But the <a
981 href="{@docRoot}resources/samples/WeatherListWidget/index.html">
982 WeatherListWidget sample</a> has two layout files:
983 <code>dark_widget_item.xml</code> and <code>light_widget_item.xml</code>.</p>
987 <h4 id="AppWidgetProvider-collections">AppWidgetProvider class for app widgets with collections</h4>
989 <p>As with a regular app widget, the bulk of your code in your {@link
990 android.appwidget.AppWidgetProvider} subclass typically goes in {@link
991 android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
992 android.appwidget.AppWidgetManager, int[]) onUpdate()}. The major difference in
993 your implementation for {@link
994 android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
995 android.appwidget.AppWidgetManager, int[]) onUpdate()} when creating an app
996 widget with collections is that you must call {@link
997 android.widget.RemoteViews#setRemoteAdapter setRemoteAdapter()}. This tells the
998 collection view where to get its data. The {@link
999 android.widget.RemoteViewsService} can then return your implementation of {@link
1000 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, and
1001 the widget can serve up the appropriate data. When you call this method, you
1002 must pass an intent that points to your implementation of {@link
1003 android.widget.RemoteViewsService} and the App Widget ID that specifies the app
1004 widget to update.</p>
1007 <p>For example, here's how the StackView Widget sample implements the {@link
1008 android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
1009 android.appwidget.AppWidgetManager, int[]) onUpdate()} callback method to set
1011 android.widget.RemoteViewsService} as the remote adapter for the app widget
1014 <pre>public void onUpdate(Context context, AppWidgetManager appWidgetManager,
1015 int[] appWidgetIds) {
1016 // update each of the app widgets with the remote adapter
1017 for (int i = 0; i < appWidgetIds.length; ++i) {
1019 // Set up the intent that starts the StackViewService, which will
1020 // provide the views for this collection.
1021 Intent intent = new Intent(context, StackWidgetService.class);
1022 // Add the app widget ID to the intent extras.
1023 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
1024 intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
1025 // Instantiate the RemoteViews object for the App Widget layout.
1026 RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
1027 // Set up the RemoteViews object to use a RemoteViews adapter.
1028 // This adapter connects
1029 // to a RemoteViewsService through the specified intent.
1030 // This is how you populate the data.
1031 rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
1033 // The empty view is displayed when the collection has no items.
1034 // It should be in the same layout used to instantiate the RemoteViews
1036 rv.setEmptyView(R.id.stack_view, R.id.empty_view);
1039 // Do additional processing specific to this app widget...
1042 appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
1044 super.onUpdate(context, appWidgetManager, appWidgetIds);
1047 <h4>RemoteViewsService class</h4>
1049 <div class="sidebox-wrapper">
1050 <div class="sidebox">
1051 <h3>Persisting data</h3>
1052 <p>You can’t rely on a single instance of your service, or any data it
1053 contains, to persist. You should therefore not store any data in your {@link
1054 android.widget.RemoteViewsService} (unless it is static). If you want your
1055 app widget’s data to persist, the best approach is to use a {@link
1056 android.content.ContentProvider} whose data persists beyond the process
1057 lifecycle.</p> </div>
1060 <p>As described above, your {@link android.widget.RemoteViewsService} subclass
1061 provides the {@link android.widget.RemoteViewsService.RemoteViewsFactory
1062 RemoteViewsFactory} used to populate the remote collection view.</p>
1064 <p>Specifically, you need to
1065 perform these steps:</p>
1068 <li>Subclass {@link android.widget.RemoteViewsService}. {@link
1069 android.widget.RemoteViewsService} is the service through which
1070 a remote adapter can request {@link android.widget.RemoteViews}. </li>
1072 <li>In your {@link android.widget.RemoteViewsService} subclass, include a
1073 class that implements the {@link
1074 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1075 interface. {@link android.widget.RemoteViewsService.RemoteViewsFactory
1076 RemoteViewsFactory} is an interface for an adapter between a remote collection
1077 view (such as {@link android.widget.ListView}, {@link android.widget.GridView},
1078 and so on) and the underlying data for that view. Your implementation is
1079 responsible for making a {@link android.widget.RemoteViews} object for each
1080 item in the data set. This interface is a thin wrapper around {@link
1081 android.widget.Adapter}.</li>
1084 <p>The primary contents of the {@link android.widget.RemoteViewsService}
1085 implementation is its {@link
1086 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory},
1087 described below.</p>
1089 <h4>RemoteViewsFactory interface</h4>
1091 <p>Your custom class that implements the {@link
1092 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1093 interface provides the app widget with the data for the items in its collection.
1095 do this, it combines your app widget item XML layout file with a source of data.
1096 This source of data could be anything from a database to a simple array. In the
1097 <a href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1098 sample</a>, the data source is an array of <code>WidgetItems</code>. The {@link
1099 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1100 functions as an adapter to glue the data to the remote collection view.</p>
1102 <p>The two most important methods you need to implement for your
1104 {@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1106 {@link android.widget.RemoteViewsService.RemoteViewsFactory#onCreate()
1108 {@link android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int)
1112 <p>The system calls {@link
1113 android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} when
1114 creating your factory for the first time. This is where you set up any
1115 connections and/or cursors to your data source. For example, the <a
1116 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1117 sample</a> uses {@link
1118 android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} to
1119 initialize an array of <code>WidgetItem</code> objects. When your app widget is
1120 active, the system accesses these objects using their index position in the
1121 array and the text they contain is displayed </p>
1123 <p>Here is an excerpt from the <a
1124 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget</a>
1126 {@link android.widget.RemoteViewsService.RemoteViewsFactory
1127 RemoteViewsFactory} implementation that shows portions of the {@link
1128 android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()}
1131 <pre>class StackRemoteViewsFactory implements
1132 RemoteViewsService.RemoteViewsFactory {
1133 private static final int mCount = 10;
1134 private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
1135 private Context mContext;
1136 private int mAppWidgetId;
1138 public StackRemoteViewsFactory(Context context, Intent intent) {
1140 mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1141 AppWidgetManager.INVALID_APPWIDGET_ID);
1144 public void onCreate() {
1145 // In onCreate() you setup any connections / cursors to your data source. Heavy lifting,
1146 // for example downloading or creating content etc, should be deferred to onDataSetChanged()
1147 // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
1148 for (int i = 0; i < mCount; i++) {
1149 mWidgetItems.add(new WidgetItem(i + "!"));
1155 <p>The {@link android.widget.RemoteViewsService.RemoteViewsFactory
1156 RemoteViewsFactory} method {@link
1157 android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()}
1158 returns a {@link android.widget.RemoteViews} object corresponding to the data at
1159 the specified <code>position</code> in the data set. Here is an excerpt from
1161 href="http://developer.android.com/resources/samples/StackWidget/index.html">
1162 StackView Widget</a> sample's {@link
1163 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1166 <pre>public RemoteViews getViewAt(int position) {
1168 // Construct a remote views item based on the app widget item XML file,
1169 // and set the text based on the position.
1170 RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
1171 rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
1174 // Return the remote views object.
1178 <h4 id="behavior">Adding behavior to individual items</h4>
1180 <p>The above sections show you how to bind your data to your app widget
1181 collection. But what if you want to add dynamic behavior to the individual items
1182 in your collection view?</p>
1184 <p> As described in <a href="#AppWidgetProvider">Using the AppWidgetProvider
1185 Class</a>, you normally use {@link
1186 android.widget.RemoteViews#setOnClickPendingIntent(int,
1187 android.app.PendingIntent) setOnClickPendingIntent()} to set an object's click
1188 behavior—such as to cause a button to launch an {@link
1189 android.app.Activity}. But this approach is not allowed for child views in an
1190 individual collection item (to clarify, you could use {@link
1191 android.widget.RemoteViews#setOnClickPendingIntent(int,
1192 android.app.PendingIntent) setOnClickPendingIntent()} to set up a global button
1193 in the Gmail app widget that launches the app, for example, but not on the
1194 individual list items). Instead, to add click behavior to individual items in a
1195 collection, you use {@link
1196 android.widget.RemoteViews#setOnClickFillInIntent(int, android.content.Intent)
1197 setOnClickFillInIntent()}. This entails setting up up a pending intent template
1198 for your collection view, and then setting a fill-in intent on each item in the
1199 collection via your {@link android.widget.RemoteViewsService.RemoteViewsFactory
1200 RemoteViewsFactory}.</p>
1201 <p>This section uses the <a
1202 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1203 sample</a> to describe how to add behavior to individual items. In the <a
1204 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1205 sample</a>, if the user touches the top view, the app widget displays the {@link
1206 android.widget.Toast} message "Touched view <em>n</em>," where
1207 <em>n</em> is the index (position) of the touched view. This is how it
1211 <li>The <code>StackWidgetProvider</code> (an {@link
1212 android.appwidget.AppWidgetProvider} subclass) creates a pending intent that has
1213 a custom action called <code>TOAST_ACTION</code>.</li>
1214 <li>When the user touches a view, the intent is fired and it broadcasts
1215 <code>TOAST_ACTION</code>.</li>
1217 <li>This broadcast is intercepted by the <code>StackWidgetProvider</code>'s
1218 {@link android.appwidget.AppWidgetProvider#onReceive(android.content.Context,
1219 android.content.Intent) onReceive()} method, and the app widget displays the
1221 android.widget.Toast} message for the touched view. The data for the collection
1222 items is provided by the {@link
1223 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, via
1224 the {@link android.widget.RemoteViewsService}.</li>
1227 <p class="note"><strong>Note:</strong> The <a
1228 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1229 sample</a> uses a broadcast, but typically an app widget would simply launch an
1230 activity in a scenario like this one.</p>
1232 <h5>Setting up the pending intent template</h5>
1234 <p>The <code>StackWidgetProvider</code> ({@link
1235 android.appwidget.AppWidgetProvider} subclass) sets up a pending intent.
1236 Individuals items of a collection cannot set up their own pending intents.
1237 Instead, the collection as a whole sets up a pending intent template, and the
1238 individual items set a fill-in intent to create unique behavior on an
1242 <p>This class also receives the broadcast that is sent when the user touches a
1243 view. It processes this event in its {@link
1244 android.appwidget.AppWidgetProvider#onReceive(android.content.Context,
1245 android.content.Intent) onReceive()} method. If the intent's action is
1246 <code>TOAST_ACTION</code>, the app widget displays a {@link
1247 android.widget.Toast}
1248 message for the current view.</p>
1250 <pre>public class StackWidgetProvider extends AppWidgetProvider {
1251 public static final String TOAST_ACTION = "com.example.android.stackwidget.TOAST_ACTION";
1252 public static final String EXTRA_ITEM = "com.example.android.stackwidget.EXTRA_ITEM";
1256 // Called when the BroadcastReceiver receives an Intent broadcast.
1257 // Checks to see whether the intent's action is TOAST_ACTION. If it is, the app widget
1258 // displays a Toast message for the current item.
1260 public void onReceive(Context context, Intent intent) {
1261 AppWidgetManager mgr = AppWidgetManager.getInstance(context);
1262 if (intent.getAction().equals(TOAST_ACTION)) {
1263 int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1264 AppWidgetManager.INVALID_APPWIDGET_ID);
1265 int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0);
1266 Toast.makeText(context, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show();
1268 super.onReceive(context, intent);
1272 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
1273 // update each of the app widgets with the remote adapter
1274 for (int i = 0; i < appWidgetIds.length; ++i) {
1276 // Sets up the intent that points to the StackViewService that will
1277 // provide the views for this collection.
1278 Intent intent = new Intent(context, StackWidgetService.class);
1279 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
1280 // When intents are compared, the extras are ignored, so we need to embed the extras
1281 // into the data so that the extras will not be ignored.
1282 intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
1283 RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
1284 rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
1286 // The empty view is displayed when the collection has no items. It should be a sibling
1287 // of the collection view.
1288 rv.setEmptyView(R.id.stack_view, R.id.empty_view);
1290 // This section makes it possible for items to have individualized behavior.
1291 // It does this by setting up a pending intent template. Individuals items of a collection
1292 // cannot set up their own pending intents. Instead, the collection as a whole sets
1293 // up a pending intent template, and the individual items set a fillInIntent
1294 // to create unique behavior on an item-by-item basis.
1295 Intent toastIntent = new Intent(context, StackWidgetProvider.class);
1296 // Set the action for the intent.
1297 // When the user touches a particular view, it will have the effect of
1298 // broadcasting TOAST_ACTION.
1299 toastIntent.setAction(StackWidgetProvider.TOAST_ACTION);
1300 toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
1301 intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
1302 PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
1303 PendingIntent.FLAG_UPDATE_CURRENT);
1304 rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent);
1306 appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
1308 super.onUpdate(context, appWidgetManager, appWidgetIds);
1312 <h5><strong>Setting the fill-in Intent</strong></h5>
1314 <p>Your {@link android.widget.RemoteViewsService.RemoteViewsFactory
1315 RemoteViewsFactory} must set a fill-in intent on each item in the collection.
1316 This makes it possible to distinguish the individual on-click action of a given
1317 item. The fill-in intent is then combined with the {@link
1318 android.app.PendingIntent} template in order to determine the final intent that
1319 will be executed when the item is clicked. </p>
1322 public class StackWidgetService extends RemoteViewsService {
1324 public RemoteViewsFactory onGetViewFactory(Intent intent) {
1325 return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
1329 class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
1330 private static final int mCount = 10;
1331 private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
1332 private Context mContext;
1333 private int mAppWidgetId;
1335 public StackRemoteViewsFactory(Context context, Intent intent) {
1337 mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1338 AppWidgetManager.INVALID_APPWIDGET_ID);
1341 // Initialize the data set.
1342 public void onCreate() {
1343 // In onCreate() you set up any connections / cursors to your data source. Heavy lifting,
1344 // for example downloading or creating content etc, should be deferred to onDataSetChanged()
1345 // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
1346 for (int i = 0; i < mCount; i++) {
1347 mWidgetItems.add(new WidgetItem(i + "!"));
1353 // Given the position (index) of a WidgetItem in the array, use the item's text value in
1354 // combination with the app widget item XML file to construct a RemoteViews object.
1355 public RemoteViews getViewAt(int position) {
1356 // position will always range from 0 to getCount() - 1.
1358 // Construct a RemoteViews item based on the app widget item XML file, and set the
1359 // text based on the position.
1360 RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
1361 rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
1363 // Next, set a fill-intent, which will be used to fill in the pending intent template
1364 // that is set on the collection view in StackWidgetProvider.
1365 Bundle extras = new Bundle();
1366 extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
1367 Intent fillInIntent = new Intent();
1368 fillInIntent.putExtras(extras);
1369 // Make it possible to distinguish the individual on-click
1370 // action of a given item
1371 rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
1375 // Return the RemoteViews object.
1381 <h3 id="fresh">Keeping Collection Data Fresh</h3>
1383 <p>The following figure illustrates the flow that occurs in an App Widget that
1385 collections when updates occur. It shows how the App Widget code interacts with
1386 the {@link android.widget.RemoteViewsService.RemoteViewsFactory
1387 RemoteViewsFactory}, and how you can trigger updates:</p>
1389 <img src="{@docRoot}images/appwidgets/appwidget_collections.png" alt="" />
1391 <p>One feature of App Widgets that use collections is the ability to provide
1392 users with up-to-date content. For example, consider the Android 3.0 Gmail
1393 app widget, which provides users with a snapshot of their inbox. To make this
1394 possible, you need to be able to trigger your {@link
1395 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} and
1396 collection view to fetch and display new data. You achieve this with the {@link
1397 android.appwidget.AppWidgetManager} call {@link
1398 android.appwidget.AppWidgetManager#notifyAppWidgetViewDataChanged(int, int)
1399 notifyAppWidgetViewDataChanged()}. This call results in a callback to your
1400 <code>RemoteViewsFactory</code>’s {@link
1401 android.widget.RemoteViewsService.RemoteViewsFactory#onDataSetChanged()
1402 onDataSetChanged()} method, which gives you the opportunity to fetch any new
1403 data. Note that you can perform
1404 processing-intensive operations synchronously within the {@link
1405 android.widget.RemoteViewsService.RemoteViewsFactory#onDataSetChanged()
1406 onDataSetChanged()} callback. You are guaranteed that this call will be
1407 completed before the metadata or view data is fetched from the {@link
1408 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}. In
1409 addition, you can perform processing-intensive operations within the {@link
1410 android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()}
1411 method. If this call takes a long time, the loading view (specified by the
1412 <code>RemoteViewsFactory</code>’s {@link
1413 android.widget.RemoteViewsService.RemoteViewsFactory#getLoadingView()} method)
1414 will be displayed in the corresponding position of the collection view until it