7 <h2>In this document</h2>
9 <li><a href="#Basics">The Basics</a></li>
10 <li><a href="#Manifest">Declaring an App Widget in the Manifest</a></li>
11 <li><a href="#MetaData">Adding the AppWidgetProviderInfo Metadata</a></li>
12 <li><a href="#CreatingLayout">Creating the App Widget Layout</a></li>
13 <li><a href="#AppWidgetProvider">Using the AppWidgetProvider Class</a>
15 <li><a href="#ProviderBroadcasts">Receiving App Widget broadcast
19 <li><a href="#Configuring">Creating an App Widget Configuration
22 <li><a href="#UpdatingFromTheConfiguration">Updating the App Widget
24 the configuration Activity</a></li>
27 <li><a href="#preview">Setting a Preview Image</a></li>
28 <li><a href="#lockscreen">Enabling App Widgets on the Lockscreen
30 <li><a href="#lockscreen-sizing">Sizing guidelines</li>
33 <li><a href="#collections">Using App Widgets with Collections</a>
35 <li><a href="#collection_sample">Sample application</a></li>
36 <li><a href="#implementing_collections">Implementing app widgets with
39 <li><a href="#fresh">Keeping Collection Data Fresh</a></li>
46 <li>{@link android.appwidget.AppWidgetProvider}</li>
47 <li>{@link android.appwidget.AppWidgetProviderInfo}</li>
48 <li>{@link android.appwidget.AppWidgetManager}</li>
54 <p>App Widgets are miniature application views that can be embedded in other
56 (such as the Home screen) and receive periodic updates. These views are
58 to as Widgets in the user interface,
59 and you can publish one with an App Widget provider. An application component
61 able to hold other App Widgets is called an App Widget host. The screenshot
63 the Music App Widget.</p>
65 <img src="{@docRoot}images/appwidgets/appwidget.png" alt="" />
67 <p>This document describes how to publish an App Widget using an App Widget
70 <div class="note design">
71 <p><strong>Widget Design</strong></p>
72 <p>For information about how to design your app widget, read the <a
73 href="{@docRoot}design/patterns/widgets.html">Widgets</a> design guide.</p>
77 <h2 id="Basics">The Basics</h2>
79 <p>To create an App Widget, you need the following:</p>
82 <dt>{@link android.appwidget.AppWidgetProviderInfo} object</dt>
83 <dd>Describes the metadata for an App Widget, such as the App Widget's layout,
85 and the AppWidgetProvider class. This should be defined in XML.</dd>
86 <dt>{@link android.appwidget.AppWidgetProvider} class implementation</dt>
87 <dd>Defines the basic methods that allow you to programmatically interface
89 based on broadcast events. Through it, you will receive broadcasts when the
90 App Widget is updated,
91 enabled, disabled and deleted.</dd>
93 <dd>Defines the initial layout for the App Widget, defined in XML.</dd>
96 <p>Additionally, you can implement an App Widget configuration Activity. This is
98 {@link android.app.Activity} that launches when the user adds your App Widget
100 to modify App Widget settings at create-time.</p>
102 <p>The following sections describe how to setup each of these components.</p>
105 <h2 id="Manifest">Declaring an App Widget in the Manifest</h2>
107 <p>First, declare the {@link android.appwidget.AppWidgetProvider} class in your
109 <code>AndroidManifest.xml</code> file. For example:</p>
111 <pre style="clear:right">
112 <receiver android:name="ExampleAppWidgetProvider" >
114 <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
116 <meta-data android:name="android.appwidget.provider"
117 android:resource="@xml/example_appwidget_info" />
121 <p>The <code><receiver></code> element requires the
122 <code>android:name</code>
123 attribute, which specifies the {@link android.appwidget.AppWidgetProvider} used
124 by the App Widget.</p>
126 <p>The <code><intent-filter></code> element must include an
127 <code><action></code>
128 element with the <code>android:name</code> attribute. This attribute specifies
129 that the {@link android.appwidget.AppWidgetProvider} accepts the {@link
130 android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE
131 ACTION_APPWIDGET_UPDATE} broadcast.
132 This is the only broadcast that you must explicitly declare. The {@link
133 android.appwidget.AppWidgetManager}
134 automatically sends all other App Widget broadcasts to the AppWidgetProvider as
137 <p>The <code><meta-data></code> element specifies the
138 {@link android.appwidget.AppWidgetProviderInfo} resource and requires the
139 following attributes:</p>
141 <li><code>android:name</code> - Specifies the metadata name. Use
142 <code>android.appwidget.provider</code>
143 to identify the data as the {@link android.appwidget.AppWidgetProviderInfo}
145 <li><code>android:resource</code> - Specifies the {@link
146 android.appwidget.AppWidgetProviderInfo}
147 resource location.</li>
151 <h2 id="MetaData">Adding the AppWidgetProviderInfo Metadata</h2>
153 <p>The {@link android.appwidget.AppWidgetProviderInfo} defines the essential
154 qualities of an App Widget, such as its minimum layout dimensions, its initial
156 how often to update the App Widget, and (optionally) a configuration Activity to
157 launch at create-time.
158 Define the AppWidgetProviderInfo object in an XML resource using a single
159 <code><appwidget-provider></code> element and save it in the project's
160 <code>res/xml/</code>
166 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
167 android:minWidth="294dp"
168 android:minHeight="72dp"
169 android:updatePeriodMillis="86400000"
170 android:previewImage="@drawable/preview"
171 android:initialLayout="@layout/example_appwidget"
172 android:configure="com.example.android.ExampleAppWidgetConfigure"
173 android:resizeMode="horizontal|vertical"
174 android:widgetCategory="home_screen|keyguard"
175 android:initialKeyguardLayout="@layout/example_keyguard">
176 </appwidget-provider>
179 <p>Here's a summary of the <code><appwidget-provider></code> attributes:</p>
181 <li>The values for the <code>minWidth</code> and <code>minHeight</code>
182 attributes specify the minimum amount of space the App Widget consumes
183 <em>by default</em>. The default Home screen positions App Widgets in its
184 window based on a grid of cells that have a defined height and width. If
185 the values for an App Widget's minimum width or height don't match the
186 dimensions of the cells, then the App Widget dimensions round
187 <em>up</em> to the nearest cell size.
188 <p>See the <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size">
189 App Widget Design Guidelines</a> for more information on sizing your App
192 <p class="note"><strong>Note:</strong> To make your app widget portable
193 across devices, your app widget's minimum size should never be larger
194 than 4 x 4 cells.</p>
197 <li>The <code>minResizeWidth</code> and <code>minResizeHeight</code> attributes
198 specify the App Widget's absolute minimum size. These values should specify
199 the size below which the App Widget would be illegible or otherwise unusable.
200 Using these attributes allows the user to resize the widget to a size that
201 may be smaller than the default widget size defined by the
202 <code>minWidth</code> and <code>minHeight</code> attributes.
203 Introduced in Android 3.1.
205 <p>See the <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size">
206 App Widget Design Guidelines</a> for more information on sizing your App
210 <li>The <code>updatePeriodMillis</code> attribute defines how often the App
211 Widget framework should request an update from the {@link
212 android.appwidget.AppWidgetProvider} by calling the
213 {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()}
214 callback method. The actual update
215 is not guaranteed to occur exactly on time with this value and we suggest
216 updating as infrequently as possible—perhaps no more than once an hour to
217 conserve the battery. You might also allow the user to adjust the frequency in a
218 configuration—some people might want a stock ticker to update every 15
219 minutes, or maybe only four times a day.
220 <p class="note"><strong>Note:</strong> If the device is asleep when it
221 is time for an update
222 (as defined by <code>updatePeriodMillis</code>), then the device will
224 to perform the update. If you don't update more than once per hour, this
226 cause significant problems for the battery life. If, however, you need
228 frequently and/or you do not need to update while the device is asleep,
230 perform updates based on an alarm that will not wake the device. To do
231 so, set an alarm with
232 an Intent that your AppWidgetProvider receives, using the {@link
233 android.app.AlarmManager}.
234 Set the alarm type to either {@link
235 android.app.AlarmManager#ELAPSED_REALTIME} or
236 {@link android.app.AlarmManager#RTC}, which will only
237 deliver the alarm when the device is awake. Then set
238 <code>updatePeriodMillis</code> to
239 zero (<code>"0"</code>).</p>
241 <li>The <code>initialLayout</code> attribute points to the layout resource
243 App Widget layout.</li>
244 <li>The <code>configure</code> attribute defines the {@link
245 android.app.Activity} to launch when
246 the user adds the App Widget, in order for him or her to configure App
247 Widget properties. This is optional
248 (read <a href="#Configuring">Creating an App Widget Configuration
249 Activity</a> below).</li>
251 <li>The <code>previewImage</code> attribute specifies a preview of what the
252 app widget will look like after it's configured, which the user sees when
253 selecting the app widget. If not supplied, the user instead sees your
254 application's launcher icon. This field corresponds to the
255 <code>android:previewImage</code> attribute in the <code><receiver></code>
256 element in the <code>AndroidManifest.xml</code> file. For more discussion of
257 using <code>previewImage</code>, see <a href="#preview">Setting a Preview
258 Image</a>. Introduced in Android 3.0.</li>
260 <li>The <code>autoAdvanceViewId</code> attribute specifies the view ID of the
261 app widget subview that should be auto-advanced by the widget's host. Introduced in Android 3.0.</li>
263 <li>The <code>resizeMode</code> attribute specifies the rules by which a widget
264 can be resized. You use this attribute to make homescreen widgets
265 resizeable—horizontally, vertically, or on both axes. Users touch-hold a
266 widget to show its resize handles, then drag the horizontal and/or vertical
267 handles to change the size on the layout grid. Values for the
268 <code>resizeMode</code> attribute include "horizontal", "vertical", and "none".
269 To declare a widget as resizeable horizontally and vertically, supply the value
270 "horizontal|vertical". Introduced in Android 3.1.</li>
272 <li>The <code>widgetCategory</code> attribute declares whether your App Widget can be displayed on the home screen,
273 the lock screen (keyguard), or both. Values for this attribute include "home_screen" and "keyguard". A widget that
274 is displayed on both needs to ensure that it follows the design guidelines for both widget classes. For more
275 information, see <a href="#lockscreen">Enabling App Widgets on the Lockscreen</a>. The default value is "home_screen". Introduced in Android 4.2.
278 <li>The <code>initialKeyguardLayout</code> attribute points to the layout resource
279 that defines the lock screen App Widget layout. This works the same way as the
280 {@link android.appwidget.AppWidgetProviderInfo#initialLayout android:initialLayout},
281 in that it provides a layout that can appear immediately until your app widget is initialized and able to update
282 the layout. Introduced in Android 4.2.</li>
286 <p>See the {@link android.appwidget.AppWidgetProviderInfo} class for more
288 attributes accepted by the <code><appwidget-provider></code> element.</p>
291 <h2 id="CreatingLayout">Creating the App Widget Layout</h2>
293 <p>You must define an initial layout for your App Widget in XML and save it in
295 <code>res/layout/</code> directory. You can design your App Widget using the
297 below, but before you begin designing your App Widget, please read and
299 <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html">App Widget
303 <p>Creating the App Widget layout is simple if you're
305 href="{@docRoot}guide/topics/ui/declaring-layout.html">Layouts</a>.
306 However, you must be aware that App Widget layouts are based on {@link
307 android.widget.RemoteViews},
308 which do not support every kind of layout or view widget.</p>
310 <p>A RemoteViews object (and, consequently, an App Widget) can support the
311 following layout classes:</p>
314 <li>{@link android.widget.FrameLayout}</li>
315 <li>{@link android.widget.LinearLayout}</li>
316 <li>{@link android.widget.RelativeLayout}</li>
317 <li>{@link android.widget.GridLayout}</li>
320 <p>And the following widget classes:</p>
322 <li>{@link android.widget.AnalogClock}</li>
323 <li>{@link android.widget.Button}</li>
324 <li>{@link android.widget.Chronometer}</li>
325 <li>{@link android.widget.ImageButton}</li>
326 <li>{@link android.widget.ImageView}</li>
327 <li>{@link android.widget.ProgressBar}</li>
328 <li>{@link android.widget.TextView}</li>
329 <li>{@link android.widget.ViewFlipper}</li>
330 <li>{@link android.widget.ListView}</li>
331 <li>{@link android.widget.GridView}</li>
332 <li>{@link android.widget.StackView}</li>
333 <li>{@link android.widget.AdapterViewFlipper}</li>
336 <p>Descendants of these classes are not supported.</p>
338 <p>RemoteViews also supports {@link android.view.ViewStub}, which is an invisible, zero-sized View you can use
339 to lazily inflate layout resources at runtime.</p>
342 <h3 id="AddingMargins">Adding margins to App Widgets</h3>
344 <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>
346 <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>
348 <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>
351 <li>Set your application's <code>targetSdkVersion</code> to 14 or greater.</li>
352 <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:
356 android:layout_width="match_parent"
357 android:layout_height="match_parent"
358 <strong>android:padding="@dimen/widget_margin"></strong>
361 android:layout_width="match_parent"
362 android:layout_height="match_parent"
363 android:orientation="horizontal"
364 android:background="@drawable/my_widget_background">
366 </LinearLayout>
372 <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:
374 <p><strong>res/values/dimens.xml</strong>:<br>
375 <pre><dimen name="widget_margin">8dp</dimen></pre></p>
377 <p><strong>res/values-v14/dimens.xml</strong>:<br>
378 <pre><dimen name="widget_margin">0dp</dimen></pre></p>
382 <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>
385 <h2 id="AppWidgetProvider">Using the AppWidgetProvider Class</h2>
387 <div class="sidebox-wrapper">
388 <div class="sidebox">
389 <p>You must declare your AppWidgetProvider class implementation as a
391 using the <code><receiver></code> element in the AndroidManifest (see
392 <a href="#Manifest">Declaring an App Widget in the Manifest</a> above).</p>
396 <p>The {@link android.appwidget.AppWidgetProvider} class extends
397 BroadcastReceiver as a convenience
398 class to handle the App Widget broadcasts. The AppWidgetProvider receives only
399 the event broadcasts that
400 are relevant to the App Widget, such as when the App Widget is updated, deleted,
401 enabled, and disabled.
402 When these broadcast events occur, the AppWidgetProvider receives the following
407 {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()}
409 <dd>This is called to update the App Widget at intervals defined by the
410 <code>updatePeriodMillis</code>
411 attribute in the AppWidgetProviderInfo (see <a href="#MetaData">Adding the
412 AppWidgetProviderInfo Metadata</a> above). This method is also called
413 when the user adds the App Widget, so it should perform the essential setup,
414 such as define event handlers for Views and start a temporary
415 {@link android.app.Service}, if necessary. However, if you have declared a
417 Activity, <strong>this method is not called</strong> when the user adds the
419 but is called for the subsequent updates. It is the responsibility of the
420 configuration Activity to perform the first update when configuration is
422 (See <a href="#Configuring">Creating an App Widget Configuration
423 Activity</a> below.)</dd>
426 {@link android.appwidget.AppWidgetProvider#onAppWidgetOptionsChanged onAppWidgetOptionsChanged()}
429 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 />
431 <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_WIDTH}—Contains
432 the lower bound on the current width, in dp units, of a widget instance.</li>
433 <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_HEIGHT}—Contains
434 the lower bound on the current height, in dp units, of a widget instance.</li>
435 <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_WIDTH}—Contains
436 the upper bound on the current width, in dp units, of a widget instance.</li>
437 <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_HEIGHT}—Contains
438 the upper bound on the current width, in dp units, of a widget instance.</li>
441 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.
443 <dt>{@link android.appwidget.AppWidgetProvider#onDeleted(Context,int[])}</dt>
444 <dd>This is called every time an App Widget is deleted from the App Widget
446 <dt>{@link android.appwidget.AppWidgetProvider#onEnabled(Context)}</dt>
447 <dd>This is called when an instance the App Widget is created for the first
448 time. For example, if the user
449 adds two instances of your App Widget, this is only called the first time.
450 If you need to open a new database or perform other setup that only needs to
452 for all App Widget instances, then this is a good place to do it.</dd>
453 <dt>{@link android.appwidget.AppWidgetProvider#onDisabled(Context)}</dt>
454 <dd>This is called when the last instance of your App Widget is deleted from
456 This is where you should clean up any work done in
457 {@link android.appwidget.AppWidgetProvider#onEnabled(Context)},
458 such as delete a temporary database.</dd>
459 <dt>{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)}</dt>
460 <dd>This is called for every broadcast and before each of the above callback
462 You normally don't need to implement this method because the default
464 implementation filters all App Widget broadcasts and calls the above
465 methods as appropriate.</dd>
468 <p class="warning"><strong>Note:</strong> In Android 1.5, there is a known issue
470 <code>onDeleted()</code> method will not be called when it should be. To work
472 you can implement {@link
473 android.appwidget.AppWidgetProvider#onReceive(Context,Intent)
474 onReceive()} as described in this
476 href="http://groups.google.com/group/android-developers/msg/e405ca19df2170e2">
478 to receive the <code>onDeleted()</code> callback.
481 <p>The most important AppWidgetProvider callback is
482 {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()}
483 because it is called when
484 each App Widget is added to a host (unless you use a configuration Activity). If
485 your App Widget accepts any user interaction events, then you need to register
486 the event handlers in this callback. If your App Widget doesn't create temporary
487 files or databases, or perform other work that requires clean-up, then
488 {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()}
489 may be the only callback
490 method you need to define. For example, if you want an App Widget with a button
491 that launches an Activity when clicked, you could use the following
492 implementation of AppWidgetProvider:</p>
495 public class ExampleAppWidgetProvider extends AppWidgetProvider {
497 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
498 final int N = appWidgetIds.length;
500 // Perform this loop procedure for each App Widget that belongs to this provider
501 for (int i=0; i<N; i++) {
502 int appWidgetId = appWidgetIds[i];
504 // Create an Intent to launch ExampleActivity
505 Intent intent = new Intent(context, ExampleActivity.class);
506 PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
508 // Get the layout for the App Widget and attach an on-click listener
510 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
511 views.setOnClickPendingIntent(R.id.button, pendingIntent);
513 // Tell the AppWidgetManager to perform an update on the current app widget
514 appWidgetManager.updateAppWidget(appWidgetId, views);
520 <p>This AppWidgetProvider defines only the
522 android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()}
523 method for the purpose of
524 defining a {@link android.app.PendingIntent} that launches an {@link
525 android.app.Activity} and attaching it to the App Widget's button with {@link
526 android.widget.RemoteViews#setOnClickPendingIntent(int,PendingIntent)}. Notice
527 that it includes a loop that iterates through each entry in
528 <code>appWidgetIds</code>, which is an array of IDs that identify each App
529 Widget created by this provider. In this way, if the user creates more than one
530 instance of the App Widget, then they are all updated simultaneously. However,
531 only one <code>updatePeriodMillis</code> schedule will be managed for all
532 instances of the App Widget. For example, if the update schedule is defined to
533 be every two hours, and a second instance of the App Widget is added one hour
534 after the first one, then they will both be updated on the period defined by the
535 first one and the second update period will be ignored (they'll both be updated
536 every two hours, not every hour).</p>
538 <p class="note"><strong>Note:</strong> Because {@link
539 android.appwidget.AppWidgetProvider} is an extension of {@link
540 android.content.BroadcastReceiver}, your process is not guaranteed to keep
541 running after the callback methods return (see {@link
542 android.content.BroadcastReceiver} for information about the broadcast
543 lifecycle). If your App Widget setup process can take several seconds (perhaps
544 while performing web requests) and you require that your process continues,
545 consider starting a {@link android.app.Service} in the
546 {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()}
547 method. From within the Service, you can perform your own updates
548 to the App Widget without worrying about the AppWidgetProvider closing down due
549 to an <a href="{@docRoot}guide/practices/responsiveness.html">Application
550 Not Responding</a> (ANR) error. See the <a
551 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
552 android.app.Service}.</p>
555 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.html">ExampleAppWidgetProvider.java</a>
559 <h3 id="ProviderBroadcasts">Receiving App Widget broadcast Intents</h3>
561 <p>{@link android.appwidget.AppWidgetProvider} is just a convenience class. If
563 to receive the App Widget broadcasts directly, you can implement your own
564 {@link android.content.BroadcastReceiver} or override the
565 {@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)} callback.
566 The Intents you need to care about are as follows:</p>
568 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE}</li>
569 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DELETED}</li>
570 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_ENABLED}</li>
571 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DISABLED}</li>
572 <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_OPTIONS_CHANGED}</li>
577 <h2 id="Configuring">Creating an App Widget Configuration Activity</h2>
579 <p>If you would like the user to configure settings when he or she adds a new
581 you can create an App Widget configuration Activity. This {@link
582 android.app.Activity}
583 will be automatically launched by the App Widget host and allows the user to
585 available settings for the App Widget at create-time, such as the App Widget
587 update period or other functionality settings.</p>
589 <p>The configuration Activity should be declared as a normal Activity in the
590 Android manifest file.
591 However, it will be launched by the App Widget host with the {@link
592 android.appwidget.AppWidgetManager#ACTION_APPWIDGET_CONFIGURE
593 ACTION_APPWIDGET_CONFIGURE} action,
594 so the Activity needs to accept this Intent. For example:</p>
597 <activity android:name=".ExampleAppWidgetConfigure">
599 <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
604 <p>Also, the Activity must be declared in the AppWidgetProviderInfo XML file,
606 <code>android:configure</code> attribute (see <a href="#MetaData">Adding
607 the AppWidgetProviderInfo Metadata</a> above). For example, the configuration
609 can be declared like this:</p>
612 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
614 android:configure="com.example.android.ExampleAppWidgetConfigure"
616 </appwidget-provider>
619 <p>Notice that the Activity is declared with a fully-qualified namespace,
621 it will be referenced from outside your package scope.</p>
623 <p>That's all you need to get started with a configuration Activity. Now all you
625 Activity. There are, however, two important things to remember when you
626 implement the Activity:</p>
628 <li>The App Widget host calls the configuration Activity and the configuration
629 Activity should always
630 return a result. The result should include the App Widget ID
631 passed by the Intent that launched the Activity (saved in the Intent extras
633 {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID}).</li>
635 {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()}
636 method <strong>will not be called</strong> when the App Widget
638 (the system will not send the ACTION_APPWIDGET_UPDATE broadcast when a
639 configuration Activity
640 is launched). It is the responsibility of the configuration Activity to
641 request an update from the
642 AppWidgetManager when the App Widget is first created. However,
643 {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()}
644 will be called for subsequent updates—it is only skipped
648 <p>See the code snippets in the following section for an example of how to
650 from the configuration and update the App Widget.</p>
653 <h3 id="UpdatingFromTheConfiguration">Updating the App Widget from the
654 configuration Activity</h3>
656 <p>When an App Widget uses a configuration Activity, it is the responsibility of
658 to update the App Widget when configuration is complete.
659 You can do so by requesting an update directly from the
660 {@link android.appwidget.AppWidgetManager}.</p>
662 <p>Here's a summary of the procedure to properly update the App Widget and close
663 the configuration Activity:</p>
666 <li>First, get the App Widget ID from the Intent that launched the Activity:
668 Intent intent = getIntent();
669 Bundle extras = intent.getExtras();
670 if (extras != null) {
671 mAppWidgetId = extras.getInt(
672 AppWidgetManager.EXTRA_APPWIDGET_ID,
673 AppWidgetManager.INVALID_APPWIDGET_ID);
677 <li>Perform your App Widget configuration.</li>
678 <li>When the configuration is complete, get an instance of the
679 AppWidgetManager by calling
680 {@link android.appwidget.AppWidgetManager#getInstance(Context)}:
682 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
685 <li>Update the App Widget with a {@link android.widget.RemoteViews} layout by
687 {@link android.appwidget.AppWidgetManager#updateAppWidget(int,RemoteViews)}:
689 RemoteViews views = new RemoteViews(context.getPackageName(),
690 R.layout.example_appwidget);
691 appWidgetManager.updateAppWidget(mAppWidgetId, views);
694 <li>Finally, create the return Intent, set it with the Activity result, and
695 finish the Activity:</li>
697 Intent resultValue = new Intent();
698 resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
699 setResult(RESULT_OK, resultValue);
705 <p class="note"><strong>Tip:</strong> When your configuration Activity first
707 the Activity result to RESULT_CANCELED. This way, if the user backs-out of the
709 reaching the end, the App Widget host is notified that the configuration was
711 App Widget will not be added.</p>
714 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetConfigure.html">ExampleAppWidgetConfigure.java</a>
715 sample class in ApiDemos for an example.</p>
717 <h2 id="preview">Setting a Preview Image</h2>
719 <p>Android 3.0 introduces the {@link
722 android.appwidget.AppWidgetProviderInfo#previewImage} field, which specifies a
723 preview of what the app widget looks like. This preview is shown to the user from the
724 widget picker. If this field is not supplied, the app widget's icon is used for
727 <p>This is how you specify this setting in XML:</p>
729 <pre><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
731 android:previewImage="@drawable/preview">
732 </appwidget-provider></pre>
734 <p>To help create a preview image for your app widget (to specify in the {@link
735 android.appwidget.AppWidgetProviderInfo#previewImage} field), the Android
736 emulator includes an application called "Widget Preview." To create a
737 preview image, launch this application, select the app widget for your
738 application and set it up how you'd like your preview image to appear, then save
739 it and place it in your application's drawable resources.</p>
741 <h2 id="lockscreen">Enabling App Widgets on the Lockscreen</h2>
743 <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>
745 <p>By default, every app widget supports placement on the Home screen, so "home_screen" is the default value for the
746 {@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>
748 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
750 android:widgetCategory="keyguard|home_screen">
751 </appwidget-provider>
754 <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.
756 You can detect whether your widget is on the lockscreen or home screen by calling
757 {@link android.appwidget.AppWidgetManager#getAppWidgetOptions getAppWidgetOptions()}
758 to get the widget's options as a {@link android.os.Bundle}. The returned bundle will include the key
759 {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_HOST_CATEGORY}, whose value will be one of {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or
760 {@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>
763 AppWidgetManager appWidgetManager;
765 Bundle myOptions = appWidgetManager.getAppWidgetOptions (widgetId);
767 // Get the value of OPTION_APPWIDGET_HOST_CATEGORY
768 int category = myOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
770 // If the value is WIDGET_CATEGORY_KEYGUARD, it's a lockscreen widget
771 boolean isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
774 <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>
777 int baseLayout = isKeyguard ? R.layout.keyguard_widget_layout : R.layout.widget_layout;
781 <p>You should also specify an initial layout for your app widget when on the lock screen with the
782 {@link android.appwidget.AppWidgetProviderInfo#initialKeyguardLayout android:initialKeyguardLayout} attribute. This works the same way as the
783 {@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>
785 <h3 id="lockscreen-sizing">Sizing guidelines</h3>
787 <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>
789 <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>
792 <li>If the widget does not mark itself as vertically resizable ({@code android:resizeMode="vertical"}), then the widget height will always be "small":
794 <li>On a phone in portrait mode, "small" is defined as the space remaining when an unlock UI is being displayed.</li>
795 <li>On tablets and landscape phones, "small" is set on a per-device basis.</li>
798 <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>
801 <h2 id="collections">Using App Widgets with Collections</h2>
803 <p>Android 3.0 introduces App Widgets with collections. These kinds of App
804 Widgets use the {@link android.widget.RemoteViewsService} to display collections
805 that are backed by remote data, such as from a <a
806 href="{@docRoot}guide/topics/providers/content-providers.html">content
807 provider</a>. The data provided by the {@link android.widget.RemoteViewsService}
808 is presented in the App Widget using one of the following view types, which
809 we’ll refer to as “collection views:”</p>
812 <dt>{@link android.widget.ListView}</dt>
813 <dd>A view that shows items in a
815 list. For an example, see the Gmail app widget. </dd>
816 <dt>{@link android.widget.GridView}</dt>
817 <dd>A view that shows items in
818 two-dimensional scrolling grid. For an example, see the Bookmarks app
820 <dt>{@link android.widget.StackView}</dt>
822 stacked card view (kind of like a rolodex), where the user can flick the front
823 card up/down to see the previous/next card, respectively. Examples include
824 the YouTube and Books app widgets. </dd>
825 <dt>{@link android.widget.AdapterViewFlipper}</dt>
826 <dd>An adapter-backed simple
828 android.widget.ViewAnimator} that animates between two or more views. Only one
829 child is shown at a time. </dd>
832 <p>As stated above, these collection views display collections backed by remote
833 data. This means that they use an {@link android.widget.Adapter} to bind their
834 user interface to their data. An {@link android.widget.Adapter} binds individual
835 items from a set of data into individual {@link android.view.View} objects.
836 Because these collection views are backed by adapters, the Android framework
837 must include extra architecture to support their use in app widgets. In the
838 context of an app widget, the {@link android.widget.Adapter} is replaced by a
839 {@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory},
840 which is simply a thin wrapper around the {@link android.widget.Adapter}
843 requested for a specific item in the collection, the {@link
844 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} creates
845 and returns the item for the collection as a {@link android.widget.RemoteViews}
847 In order to include a collection view in your app widget, you
848 must implement {@link android.widget.RemoteViewsService} and {@link
849 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}.</p>
851 <p> {@link android.widget.RemoteViewsService} is a service that allows a remote
852 adapter to request {@link
853 android.widget.RemoteViews} objects. {@link
854 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} is an
855 interface for an adapter between a collection view (such as {@link
856 android.widget.ListView}, {@link android.widget.GridView}, and so on) and the
857 underlying data for that view. From the <a
858 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
859 sample</a>, here is an example of the boilerplate code you use to implement
860 this service and interface:
864 public class StackWidgetService extends RemoteViewsService {
866 public RemoteViewsFactory onGetViewFactory(Intent intent) {
867 return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
871 class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
873 //... include adapter-like methods here. See the StackView Widget sample.
878 <h3 id="collection_sample">Sample application</h3>
880 <p>The code excerpts in this section are drawn from the <a
881 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
885 <img src="{@docRoot}images/appwidgets/StackWidget.png" alt="" />
888 <p>This sample consists of a stack of 10 views, which display the values
889 <code>"0!"</code> through <code>"9!"</code> The sample
890 app widget has these primary behaviors:</p>
894 <li>The user can vertically fling the top view in the
895 app widget to display the next or previous view. This is a built-in StackView
898 <li>Without any user interaction, the app widget automatically advances
900 its views in sequence, like a slide show. This is due to the setting
901 <code>android:autoAdvanceViewId="@id/stack_view"</code> in the
902 <code>res/xml/stackwidgetinfo.xml</code> file. This setting applies to the view
904 which in this case is the view ID of the stack view.</li>
906 <li>If the user touches the top view, the app widget displays the {@link
907 android.widget.Toast} message "Touched view <em>n</em>," where
908 <em>n</em> is the index (position) of the touched view. For more discussion of
909 how this is implemented, see
910 <a href="#behavior">Adding behavior to individual items</a>.</li>
913 <h3 id="implementing_collections">Implementing app widgets with collections</h3>
915 <p>To implement an App Widget with collections, you follow the same basic steps
916 you would use to implement any app widget. The following sections describe the
917 additional steps you need to perform to implement an App Widget with
920 <h4>Manifest for app widgets with collections</h4>
922 <p> In addition to the requirements listed in <a href="#Manifest">Declaring an
923 App Widget in the Manifest</a>, to make it possible for App Widgets with
924 collections to bind to your {@link android.widget.RemoteViewsService}, you must
925 declare the service in your manifest file with the permission {@link
926 android.Manifest.permission#BIND_REMOTEVIEWS}. This prevents other applications
927 from freely accessing your app widget's data. For example, when creating an App
928 Widget that uses {@link android.widget.RemoteViewsService} to populate a
929 collection view, the manifest entry may look like this:</p>
931 <pre><service android:name="MyWidgetService"
933 android:permission="android.permission.BIND_REMOTEVIEWS" /></pre>
935 <p>The line <code>android:name="MyWidgetService"</code>
936 refers to your subclass of {@link android.widget.RemoteViewsService}. </p>
938 <h4>Layout for app widgets with collections</h4>
940 <p>The main requirement for your app widget layout XML file is that it
941 include one of the collection views: {@link android.widget.ListView},
942 {@link android.widget.GridView}, {@link android.widget.StackView}, or
943 {@link android.widget.AdapterViewFlipper}. Here is the
944 <code>widget_layout.xml</code> for
945 the <a href="{@docRoot}resources/samples/StackWidget/index.html">StackView
946 Widget sample</a>:</p>
948 <pre><?xml version="1.0" encoding="utf-8"?>
950 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
951 android:layout_width="match_parent"
952 android:layout_height="match_parent">
953 <StackView xmlns:android="http://schemas.android.com/apk/res/android"
954 android:id="@+id/stack_view"
955 android:layout_width="match_parent"
956 android:layout_height="match_parent"
957 android:gravity="center"
958 android:loopViews="true" />
959 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
960 android:id="@+id/empty_view"
961 android:layout_width="match_parent"
962 android:layout_height="match_parent"
963 android:gravity="center"
964 android:background="@drawable/widget_item_background"
965 android:textColor="#ffffff"
966 android:textStyle="bold"
967 android:text="@string/empty_view_text"
968 android:textSize="20sp" />
969 </FrameLayout></pre>
971 <p> Note that empty views must be siblings of the collection view for which the
972 empty view represents empty state. </p>
974 <p>In addition to the layout file for your entire app widget, you must create
975 another layout file that defines the layout for each item in the collection (for
976 example, a layout for each book in a collection of books). For example, the <a
977 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
978 sample</a> only has one layout file, <code>widget_item.xml</code>, since all
979 items use the same layout. But the <a
980 href="{@docRoot}resources/samples/WeatherListWidget/index.html">
981 WeatherListWidget sample</a> has two layout files:
982 <code>dark_widget_item.xml</code> and <code>light_widget_item.xml</code>.</p>
986 <h4 id="AppWidgetProvider-collections">AppWidgetProvider class for app widgets with collections</h4>
988 <p>As with a regular app widget, the bulk of your code in your {@link
989 android.appwidget.AppWidgetProvider} subclass typically goes in {@link
990 android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
991 android.appwidget.AppWidgetManager, int[]) onUpdate()}. The major difference in
992 your implementation for {@link
993 android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
994 android.appwidget.AppWidgetManager, int[]) onUpdate()} when creating an app
995 widget with collections is that you must call {@link
996 android.widget.RemoteViews#setRemoteAdapter setRemoteAdapter()}. This tells the
997 collection view where to get its data. The {@link
998 android.widget.RemoteViewsService} can then return your implementation of {@link
999 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, and
1000 the widget can serve up the appropriate data. When you call this method, you
1001 must pass an intent that points to your implementation of {@link
1002 android.widget.RemoteViewsService} and the App Widget ID that specifies the app
1003 widget to update.</p>
1006 <p>For example, here's how the StackView Widget sample implements the {@link
1007 android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
1008 android.appwidget.AppWidgetManager, int[]) onUpdate()} callback method to set
1010 android.widget.RemoteViewsService} as the remote adapter for the app widget
1013 <pre>public void onUpdate(Context context, AppWidgetManager appWidgetManager,
1014 int[] appWidgetIds) {
1015 // update each of the app widgets with the remote adapter
1016 for (int i = 0; i < appWidgetIds.length; ++i) {
1018 // Set up the intent that starts the StackViewService, which will
1019 // provide the views for this collection.
1020 Intent intent = new Intent(context, StackWidgetService.class);
1021 // Add the app widget ID to the intent extras.
1022 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
1023 intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
1024 // Instantiate the RemoteViews object for the App Widget layout.
1025 RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
1026 // Set up the RemoteViews object to use a RemoteViews adapter.
1027 // This adapter connects
1028 // to a RemoteViewsService through the specified intent.
1029 // This is how you populate the data.
1030 rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
1032 // The empty view is displayed when the collection has no items.
1033 // It should be in the same layout used to instantiate the RemoteViews
1035 rv.setEmptyView(R.id.stack_view, R.id.empty_view);
1038 // Do additional processing specific to this app widget...
1041 appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
1043 super.onUpdate(context, appWidgetManager, appWidgetIds);
1046 <h4>RemoteViewsService class</h4>
1048 <div class="sidebox-wrapper">
1049 <div class="sidebox">
1050 <h3>Persisting data</h3>
1051 <p>You can’t rely on a single instance of your service, or any data it
1052 contains, to persist. You should therefore not store any data in your {@link
1053 android.widget.RemoteViewsService} (unless it is static). If you want your
1054 app widget’s data to persist, the best approach is to use a {@link
1055 android.content.ContentProvider} whose data persists beyond the process
1056 lifecycle.</p> </div>
1059 <p>As described above, your {@link android.widget.RemoteViewsService} subclass
1060 provides the {@link android.widget.RemoteViewsService.RemoteViewsFactory
1061 RemoteViewsFactory} used to populate the remote collection view.</p>
1063 <p>Specifically, you need to
1064 perform these steps:</p>
1067 <li>Subclass {@link android.widget.RemoteViewsService}. {@link
1068 android.widget.RemoteViewsService} is the service through which
1069 a remote adapter can request {@link android.widget.RemoteViews}. </li>
1071 <li>In your {@link android.widget.RemoteViewsService} subclass, include a
1072 class that implements the {@link
1073 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1074 interface. {@link android.widget.RemoteViewsService.RemoteViewsFactory
1075 RemoteViewsFactory} is an interface for an adapter between a remote collection
1076 view (such as {@link android.widget.ListView}, {@link android.widget.GridView},
1077 and so on) and the underlying data for that view. Your implementation is
1078 responsible for making a {@link android.widget.RemoteViews} object for each
1079 item in the data set. This interface is a thin wrapper around {@link
1080 android.widget.Adapter}.</li>
1083 <p>The primary contents of the {@link android.widget.RemoteViewsService}
1084 implementation is its {@link
1085 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory},
1086 described below.</p>
1088 <h4>RemoteViewsFactory interface</h4>
1090 <p>Your custom class that implements the {@link
1091 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1092 interface provides the app widget with the data for the items in its collection.
1094 do this, it combines your app widget item XML layout file with a source of data.
1095 This source of data could be anything from a database to a simple array. In the
1096 <a href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1097 sample</a>, the data source is an array of <code>WidgetItems</code>. The {@link
1098 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1099 functions as an adapter to glue the data to the remote collection view.</p>
1101 <p>The two most important methods you need to implement for your
1103 {@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1105 {@link android.widget.RemoteViewsService.RemoteViewsFactory#onCreate()
1107 {@link android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int)
1111 <p>The system calls {@link
1112 android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} when
1113 creating your factory for the first time. This is where you set up any
1114 connections and/or cursors to your data source. For example, the <a
1115 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1116 sample</a> uses {@link
1117 android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} to
1118 initialize an array of <code>WidgetItem</code> objects. When your app widget is
1119 active, the system accesses these objects using their index position in the
1120 array and the text they contain is displayed </p>
1122 <p>Here is an excerpt from the the <a
1123 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget</a>
1125 {@link android.widget.RemoteViewsService.RemoteViewsFactory
1126 RemoteViewsFactory} implementation that shows portions of the {@link
1127 android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()}
1130 <pre>class StackRemoteViewsFactory implements
1131 RemoteViewsService.RemoteViewsFactory {
1132 private static final int mCount = 10;
1133 private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
1134 private Context mContext;
1135 private int mAppWidgetId;
1137 public StackRemoteViewsFactory(Context context, Intent intent) {
1139 mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1140 AppWidgetManager.INVALID_APPWIDGET_ID);
1143 public void onCreate() {
1144 // In onCreate() you setup any connections / cursors to your data source. Heavy lifting,
1145 // for example downloading or creating content etc, should be deferred to onDataSetChanged()
1146 // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
1147 for (int i = 0; i < mCount; i++) {
1148 mWidgetItems.add(new WidgetItem(i + "!"));
1154 <p>The {@link android.widget.RemoteViewsService.RemoteViewsFactory
1155 RemoteViewsFactory} method {@link
1156 android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()}
1157 returns a {@link android.widget.RemoteViews} object corresponding to the data at
1158 the specified <code>position</code> in the data set. Here is an excerpt from
1160 href="http://developer.android.com/resources/samples/StackWidget/index.html">
1161 StackView Widget</a> sample's {@link
1162 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1165 <pre>public RemoteViews getViewAt(int position) {
1167 // Construct a remote views item based on the app widget item XML file,
1168 // and set the text based on the position.
1169 RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
1170 rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
1173 // Return the remote views object.
1177 <h4 id="behavior">Adding behavior to individual items</h4>
1179 <p>The above sections show you how to bind your data to your app widget
1180 collection. But what if you want to add dynamic behavior to the individual items
1181 in your collection view?</p>
1183 <p> As described in <a href="#AppWidgetProvider">Using the AppWidgetProvider
1184 Class</a>, you normally use {@link
1185 android.widget.RemoteViews#setOnClickPendingIntent(int,
1186 android.app.PendingIntent) setOnClickPendingIntent()} to set an object's click
1187 behavior—such as to cause a button to launch an {@link
1188 android.app.Activity}. But this approach is not allowed for child views in an
1189 individual collection item (to clarify, you could use {@link
1190 android.widget.RemoteViews#setOnClickPendingIntent(int,
1191 android.app.PendingIntent) setOnClickPendingIntent()} to set up a global button
1192 in the Gmail app widget that launches the app, for example, but not on the
1193 individual list items). Instead, to add click behavior to individual items in a
1194 collection, you use {@link
1195 android.widget.RemoteViews#setOnClickFillInIntent(int, android.content.Intent)
1196 setOnClickFillInIntent()}. This entails setting up up a pending intent template
1197 for your collection view, and then setting a fill-in intent on each item in the
1198 collection via your {@link android.widget.RemoteViewsService.RemoteViewsFactory
1199 RemoteViewsFactory}.</p>
1200 <p>This section uses the <a
1201 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1202 sample</a> to describe how to add behavior to individual items. In the <a
1203 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1204 sample</a>, if the user touches the top view, the app widget displays the {@link
1205 android.widget.Toast} message "Touched view <em>n</em>," where
1206 <em>n</em> is the index (position) of the touched view. This is how it
1210 <li>The <code>StackWidgetProvider</code> (an {@link
1211 android.appwidget.AppWidgetProvider} subclass) creates a pending intent that has
1212 a custom action called <code>TOAST_ACTION</code>.</li>
1213 <li>When the user touches a view, the intent is fired and it broadcasts
1214 <code>TOAST_ACTION</code>.</li>
1216 <li>This broadcast is intercepted by the <code>StackWidgetProvider</code>'s
1217 {@link android.appwidget.AppWidgetProvider#onReceive(android.content.Context,
1218 android.content.Intent) onReceive()} method, and the app widget displays the
1220 android.widget.Toast} message for the touched view. The data for the collection
1221 items is provided by the {@link
1222 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, via
1223 the {@link android.widget.RemoteViewsService}.</li>
1226 <p class="note"><strong>Note:</strong> The <a
1227 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1228 sample</a> uses a broadcast, but typically an app widget would simply launch an
1229 activity in a scenario like this one.</p>
1231 <h5>Setting up the pending intent template</h5>
1233 <p>The <code>StackWidgetProvider</code> ({@link
1234 android.appwidget.AppWidgetProvider} subclass) sets up a pending intent.
1235 Individuals items of a collection cannot set up their own pending intents.
1236 Instead, the collection as a whole sets up a pending intent template, and the
1237 individual items set a fill-in intent to create unique behavior on an
1241 <p>This class also receives the broadcast that is sent when the user touches a
1242 view. It processes this event in its {@link
1243 android.appwidget.AppWidgetProvider#onReceive(android.content.Context,
1244 android.content.Intent) onReceive()} method. If the intent's action is
1245 <code>TOAST_ACTION</code>, the app widget displays a {@link
1246 android.widget.Toast}
1247 message for the current view.</p>
1249 <pre>public class StackWidgetProvider extends AppWidgetProvider {
1250 public static final String TOAST_ACTION = "com.example.android.stackwidget.TOAST_ACTION";
1251 public static final String EXTRA_ITEM = "com.example.android.stackwidget.EXTRA_ITEM";
1255 // Called when the BroadcastReceiver receives an Intent broadcast.
1256 // Checks to see whether the intent's action is TOAST_ACTION. If it is, the app widget
1257 // displays a Toast message for the current item.
1259 public void onReceive(Context context, Intent intent) {
1260 AppWidgetManager mgr = AppWidgetManager.getInstance(context);
1261 if (intent.getAction().equals(TOAST_ACTION)) {
1262 int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1263 AppWidgetManager.INVALID_APPWIDGET_ID);
1264 int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0);
1265 Toast.makeText(context, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show();
1267 super.onReceive(context, intent);
1271 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
1272 // update each of the app widgets with the remote adapter
1273 for (int i = 0; i < appWidgetIds.length; ++i) {
1275 // Sets up the intent that points to the StackViewService that will
1276 // provide the views for this collection.
1277 Intent intent = new Intent(context, StackWidgetService.class);
1278 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
1279 // When intents are compared, the extras are ignored, so we need to embed the extras
1280 // into the data so that the extras will not be ignored.
1281 intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
1282 RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
1283 rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
1285 // The empty view is displayed when the collection has no items. It should be a sibling
1286 // of the collection view.
1287 rv.setEmptyView(R.id.stack_view, R.id.empty_view);
1289 // This section makes it possible for items to have individualized behavior.
1290 // It does this by setting up a pending intent template. Individuals items of a collection
1291 // cannot set up their own pending intents. Instead, the collection as a whole sets
1292 // up a pending intent template, and the individual items set a fillInIntent
1293 // to create unique behavior on an item-by-item basis.
1294 Intent toastIntent = new Intent(context, StackWidgetProvider.class);
1295 // Set the action for the intent.
1296 // When the user touches a particular view, it will have the effect of
1297 // broadcasting TOAST_ACTION.
1298 toastIntent.setAction(StackWidgetProvider.TOAST_ACTION);
1299 toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
1300 intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
1301 PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
1302 PendingIntent.FLAG_UPDATE_CURRENT);
1303 rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent);
1305 appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
1307 super.onUpdate(context, appWidgetManager, appWidgetIds);
1311 <h5><strong>Setting the fill-in Intent</strong></h5>
1313 <p>Your {@link android.widget.RemoteViewsService.RemoteViewsFactory
1314 RemoteViewsFactory} must set a fill-in intent on each item in the collection.
1315 This makes it possible to distinguish the individual on-click action of a given
1316 item. The fill-in intent is then combined with the {@link
1317 android.app.PendingIntent} template in order to determine the final intent that
1318 will be executed when the item is clicked. </p>
1321 public class StackWidgetService extends RemoteViewsService {
1323 public RemoteViewsFactory onGetViewFactory(Intent intent) {
1324 return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
1328 class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
1329 private static final int mCount = 10;
1330 private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
1331 private Context mContext;
1332 private int mAppWidgetId;
1334 public StackRemoteViewsFactory(Context context, Intent intent) {
1336 mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1337 AppWidgetManager.INVALID_APPWIDGET_ID);
1340 // Initialize the data set.
1341 public void onCreate() {
1342 // In onCreate() you set up any connections / cursors to your data source. Heavy lifting,
1343 // for example downloading or creating content etc, should be deferred to onDataSetChanged()
1344 // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
1345 for (int i = 0; i < mCount; i++) {
1346 mWidgetItems.add(new WidgetItem(i + "!"));
1352 // Given the position (index) of a WidgetItem in the array, use the item's text value in
1353 // combination with the app widget item XML file to construct a RemoteViews object.
1354 public RemoteViews getViewAt(int position) {
1355 // position will always range from 0 to getCount() - 1.
1357 // Construct a RemoteViews item based on the app widget item XML file, and set the
1358 // text based on the position.
1359 RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
1360 rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
1362 // Next, set a fill-intent, which will be used to fill in the pending intent template
1363 // that is set on the collection view in StackWidgetProvider.
1364 Bundle extras = new Bundle();
1365 extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
1366 Intent fillInIntent = new Intent();
1367 fillInIntent.putExtras(extras);
1368 // Make it possible to distinguish the individual on-click
1369 // action of a given item
1370 rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
1374 // Return the RemoteViews object.
1380 <h3 id="fresh">Keeping Collection Data Fresh</h3>
1382 <p>The following figure illustrates the flow that occurs in an App Widget that
1384 collections when updates occur. It shows how the App Widget code interacts with
1385 the {@link android.widget.RemoteViewsService.RemoteViewsFactory
1386 RemoteViewsFactory}, and how you can trigger updates:</p>
1388 <img src="{@docRoot}images/appwidgets/appwidget_collections.png" alt="" />
1390 <p>One feature of App Widgets that use collections is the ability to provide
1391 users with up-to-date content. For example, consider the Android 3.0 Gmail
1392 app widget, which provides users with a snapshot of their inbox. To make this
1393 possible, you need to be able to trigger your {@link
1394 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} and
1395 collection view to fetch and display new data. You achieve this with the {@link
1396 android.appwidget.AppWidgetManager} call {@link
1397 android.appwidget.AppWidgetManager#notifyAppWidgetViewDataChanged(int, int)
1398 notifyAppWidgetViewDataChanged()}. This call results in a callback to your
1399 <code>RemoteViewsFactory</code>’s {@link
1400 android.widget.RemoteViewsService.RemoteViewsFactory#onDataSetChanged()
1401 onDataSetChanged()} method, which gives you the opportunity to fetch any new
1402 data. Note that you can perform
1403 processing-intensive operations synchronously within the {@link
1404 android.widget.RemoteViewsService.RemoteViewsFactory#onDataSetChanged()
1405 onDataSetChanged()} callback. You are guaranteed that this call will be
1406 completed before the metadata or view data is fetched from the {@link
1407 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}. In
1408 addition, you can perform processing-intensive operations within the {@link
1409 android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()}
1410 method. If this call takes a long time, the loading view (specified by the
1411 <code>RemoteViewsFactory</code>’s {@link
1412 android.widget.RemoteViewsService.RemoteViewsFactory#getLoadingView()} method)
1413 will be displayed in the corresponding position of the collection view until it