• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=App Widgets
2page.tags=home,AppWidgetProvider
3@jd:body
4
5<div id="qv-wrapper">
6  <div id="qv">
7
8    <h2>In this document</h2>
9    <ol>
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>
15        <ol>
16          <li><a href="#ProviderBroadcasts">Receiving App Widget broadcast
17Intents</a></li>
18        </ol>
19      </li>
20      <li><a href="#Configuring">Creating an App Widget Configuration
21Activity</a>
22        <ol>
23          <li><a href="#UpdatingFromTheConfiguration">Updating the App Widget
24from
25            the Configuration Activity</a></li>
26        </ol>
27      </li>
28      <li><a href="#preview">Setting a Preview Image</a></li>
29      <li><a href="#lockscreen">Enabling App Widgets on the Lockscreen</a>
30        <ol>
31          <li><a href="#lockscreen-sizing">Sizing guidelines</a></li>
32        </ol>
33      </li>
34
35      <li><a href="#collections">Using App Widgets with Collections</a>
36        <ol>
37          <li><a href="#collection_sample">Sample application</a></li>
38          <li><a href="#implementing_collections">Implementing app widgets with
39collections
40</a></li>
41          <li><a href="#fresh">Keeping Collection Data Fresh</a></li>
42        </ol>
43      </li>
44    </ol>
45
46    <h2>Key classes</h2>
47    <ol>
48      <li>{@link android.appwidget.AppWidgetProvider}</li>
49      <li>{@link android.appwidget.AppWidgetProviderInfo}</li>
50      <li>{@link android.appwidget.AppWidgetManager}</li>
51    </ol>
52  </div>
53</div>
54
55
56<p>App Widgets are miniature application views that can be embedded in other
57applications
58(such as the Home screen) and receive periodic updates. These views are
59referred
60to as Widgets in the user interface,
61and you can publish one with an App Widget provider. An application component
62that is
63able to hold other App Widgets is called an App Widget host. The screenshot
64below shows
65the Music App Widget.</p>
66
67<img src="{@docRoot}images/appwidgets/appwidget.png" alt="" />
68
69<p>This document describes how to publish an App Widget using an App Widget
70provider. For a discussion of creating your own {@link android.appwidget.AppWidgetHost}
71to host app widgets, see <a href="{@docRoot}guide/topics/appwidgets/host.html">
72App Widget Host</a>.</p>
73
74<div class="note design">
75<p><strong>Widget Design</strong></p>
76  <p>For information about how to design your app widget, read the <a
77href="{@docRoot}design/patterns/widgets.html">Widgets</a> design guide.</p>
78</div>
79
80
81<h2 id="Basics">The Basics</h2>
82
83<p>To create an App Widget, you need the following:</p>
84
85<dl>
86  <dt>{@link android.appwidget.AppWidgetProviderInfo} object</dt>
87  <dd>Describes the metadata for an App Widget, such as the App Widget's layout,
88update frequency,
89    and the AppWidgetProvider class. This should be defined in XML.</dd>
90  <dt>{@link android.appwidget.AppWidgetProvider} class implementation</dt>
91  <dd>Defines the basic methods that allow you to programmatically interface
92with the App Widget,
93    based on broadcast events. Through it, you will receive broadcasts when the
94App Widget is updated,
95    enabled, disabled and deleted.</dd>
96  <dt>View layout</dt>
97  <dd>Defines the initial layout for the App Widget, defined in XML.</dd>
98</dl>
99
100<p>Additionally, you can implement an App Widget configuration Activity. This is
101an optional
102{@link android.app.Activity} that launches when the user adds your App Widget
103and allows him or her
104to modify App Widget settings at create-time.</p>
105
106<p>The following sections describe how to set up each of these components.</p>
107
108
109<h2 id="Manifest">Declaring an App Widget in the Manifest</h2>
110
111<p>First, declare the {@link android.appwidget.AppWidgetProvider} class in your
112application's
113<code>AndroidManifest.xml</code> file. For example:</p>
114
115<pre style="clear:right">
116&lt;receiver android:name="ExampleAppWidgetProvider" >
117    &lt;intent-filter>
118        &lt;action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
119    &lt;/intent-filter>
120    &lt;meta-data android:name="android.appwidget.provider"
121               android:resource="@xml/example_appwidget_info" />
122&lt;/receiver>
123</pre>
124
125<p>The <code>&lt;receiver&gt;</code> element requires the
126<code>android:name</code>
127attribute, which specifies the {@link android.appwidget.AppWidgetProvider} used
128by the App Widget.</p>
129
130<p>The <code>&lt;intent-filter&gt;</code> element must include an
131<code>&lt;action></code>
132element with the <code>android:name</code> attribute. This attribute specifies
133that the {@link android.appwidget.AppWidgetProvider} accepts the {@link
134android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE
135ACTION_APPWIDGET_UPDATE} broadcast.
136This is the only broadcast that you must explicitly declare. The {@link
137android.appwidget.AppWidgetManager}
138automatically sends all other App Widget broadcasts to the AppWidgetProvider as
139necessary.</p>
140
141<p>The <code>&lt;meta-data&gt;</code> element specifies the
142{@link android.appwidget.AppWidgetProviderInfo} resource and requires the
143following attributes:</p>
144<ul>
145  <li><code>android:name</code> - Specifies the metadata name. Use
146<code>android.appwidget.provider</code>
147    to identify the data as the {@link android.appwidget.AppWidgetProviderInfo}
148descriptor.</li>
149  <li><code>android:resource</code> - Specifies the {@link
150android.appwidget.AppWidgetProviderInfo}
151    resource location.</li>
152</ul>
153
154
155<h2 id="MetaData">Adding the AppWidgetProviderInfo Metadata</h2>
156
157<p>The {@link android.appwidget.AppWidgetProviderInfo} defines the essential
158qualities of an App Widget, such as its minimum layout dimensions, its initial
159layout resource,
160how often to update the App Widget, and (optionally) a configuration Activity to
161launch at create-time.
162Define the AppWidgetProviderInfo object in an XML resource using a single
163<code>&lt;appwidget-provider></code> element and save it in the project's
164<code>res/xml/</code>
165folder.</p>
166
167<p>For example:</p>
168
169<pre>
170&lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
171    android:minWidth="40dp"
172    android:minHeight="40dp"
173    android:updatePeriodMillis="86400000"
174    android:previewImage="@drawable/preview"
175    android:initialLayout="@layout/example_appwidget"
176    android:configure="com.example.android.ExampleAppWidgetConfigure"
177    android:resizeMode="horizontal|vertical"
178    android:widgetCategory="home_screen|keyguard"
179    android:initialKeyguardLayout="@layout/example_keyguard">
180&lt;/appwidget-provider>
181</pre>
182
183<p>Here's a summary of the <code>&lt;appwidget-provider></code> attributes:</p>
184<ul>
185  <li>The values for the <code>minWidth</code> and <code>minHeight</code>
186    attributes specify the minimum amount of space the App Widget consumes
187    <em>by default</em>. The default Home screen positions App Widgets in its
188    window based on a grid of cells that have a defined height and width. If
189    the values for an App Widget's minimum width or height don't match the
190    dimensions of the cells, then the App Widget dimensions round
191    <em>up</em> to the nearest cell size.
192    <p>See the <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size">
193    App Widget Design Guidelines</a> for more information on sizing your App
194    Widgets.</p>
195
196    <p class="note"><strong>Note:</strong> To make your app widget portable
197    across devices, your app widget's minimum size should never be larger
198    than 4 x 4 cells.</p>
199  </li>
200
201  <li>The <code>minResizeWidth</code> and <code>minResizeHeight</code> attributes
202    specify the App Widget's absolute minimum size. These values should specify
203    the size below which the App Widget would be illegible or otherwise unusable.
204    Using these attributes allows the user to resize the widget to a size that
205    may be smaller than the default widget size defined by the
206    <code>minWidth</code> and <code>minHeight</code> attributes.
207    Introduced in Android 3.1.
208
209    <p>See the <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size">
210    App Widget Design Guidelines</a> for more information on sizing your App
211    Widgets.</p>
212  </li>
213
214  <li>The <code>updatePeriodMillis</code> attribute defines how often the App
215Widget framework should request an update from the {@link
216android.appwidget.AppWidgetProvider} by calling the
217{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()}
218callback method. The actual update
219is not guaranteed to occur exactly on time with this value and we suggest
220updating as infrequently as possible&mdash;perhaps no more than once an hour to
221conserve the battery. You might also allow the user to adjust the frequency in a
222configuration&mdash;some people might want a stock ticker to update every 15
223minutes, or maybe only four times a day.
224    	<p class="note"><strong>Note:</strong> If the device is asleep when it
225is time for an update
226    	(as defined by <code>updatePeriodMillis</code>), then the device will
227wake up in order
228    	to perform the update. If you don't update more than once per hour, this
229probably won't
230    	cause significant problems for the battery life. If, however, you need
231to update more
232    	frequently and/or you do not need to update while the device is asleep,
233then you can instead
234    	perform updates based on an alarm that will not wake the device. To do
235so, set an alarm with
236    	an Intent that your AppWidgetProvider receives, using the	{@link
237android.app.AlarmManager}.
238    	Set the alarm type to either {@link
239android.app.AlarmManager#ELAPSED_REALTIME} or
240    	{@link android.app.AlarmManager#RTC}, which will only
241    	deliver the alarm when the device is awake. Then set
242<code>updatePeriodMillis</code> to
243    	zero (<code>"0"</code>).</p>
244  </li>
245  <li>The <code>initialLayout</code> attribute points to the layout resource
246that defines the
247    App Widget layout.</li>
248  <li>The <code>configure</code> attribute defines the {@link
249android.app.Activity} to launch when
250    the user adds the App Widget, in order for him or her to configure App
251Widget properties. This is optional
252    (read <a href="#Configuring">Creating an App Widget Configuration
253Activity</a> below).</li>
254
255   <li>The <code>previewImage</code> attribute specifies a preview of what the
256app widget will look like after it's configured, which the user sees when
257selecting the app widget. If not supplied, the user instead sees your
258application's launcher icon. This field corresponds to the
259<code>android:previewImage</code> attribute in the <code>&lt;receiver&gt;</code>
260element in the <code>AndroidManifest.xml</code> file. For more discussion of
261using <code>previewImage</code>, see <a href="#preview">Setting a Preview
262Image</a>. Introduced in Android 3.0.</li>
263
264   <li>The <code>autoAdvanceViewId</code> attribute specifies the view ID of the
265app widget subview that should be auto-advanced by the widget's host. Introduced in Android 3.0.</li>
266
267<li>The <code>resizeMode</code> attribute specifies the rules by which a widget
268can be resized. You use this attribute to make homescreen widgets
269resizeable&mdash;horizontally, vertically, or on both axes. Users touch-hold a
270widget to show its resize handles, then drag the horizontal and/or vertical
271handles to change the size on the layout grid. Values for the
272<code>resizeMode</code> attribute include "horizontal", "vertical", and "none".
273To declare a widget as resizeable horizontally and vertically, supply the value
274"horizontal|vertical". Introduced in Android 3.1.</li>
275
276<li>The <code>minResizeHeight</code> attribute specifies the minimum height (in dps) to which
277the widget can be resized. This field has no effect if it is greater than {@code minHeight} or if
278vertical resizing isn't enabled (see <code>resizeMode</code>). Introduced in Android 4.0.</li>
279
280<li>The <code> minResizeWidth </code> attribute specifies the minimum width (in dps) to which
281the widget can be resized. This field has no effect if it is greater than {@code minWidth} or if
282horizontal resizing isn't enabled (see <code>resizeMode</code>). Introduced in Android 4.0.</li>
283
284<li>The <code>widgetCategory</code> attribute declares whether your App Widget can be displayed on the home screen,
285the lock screen (keyguard), or both. Values for this attribute include "home_screen" and "keyguard".  A widget that
286is displayed on both needs to ensure that it follows the design guidelines for both widget classes. For more
287information, see <a href="#lockscreen">Enabling App Widgets on the Lockscreen</a>. The default value is "home_screen". Introduced in Android 4.2.
288</li>
289
290<li>The <code>initialKeyguardLayout</code> attribute points to the layout resource
291that defines the lock screen App Widget layout. This works the same way as the
292{@link android.appwidget.AppWidgetProviderInfo#initialLayout android:initialLayout},
293in that it provides a layout that can appear immediately until your app widget is initialized and able to update
294the layout. Introduced in Android 4.2.</li>
295
296</ul>
297
298<p>See the {@link android.appwidget.AppWidgetProviderInfo} class for more
299information on the
300attributes accepted by the <code>&lt;appwidget-provider></code> element.</p>
301
302
303<h2 id="CreatingLayout">Creating the App Widget Layout</h2>
304
305<p>You must define an initial layout for your App Widget in XML and save it in
306the project's
307<code>res/layout/</code> directory. You can design your App Widget using the
308View objects listed
309below, but before you begin designing your App Widget, please read and
310understand the
311<a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html">App Widget
312Design
313Guidelines</a>.</p>
314
315<p>Creating the App Widget layout is simple if you're
316familiar with <a
317href="{@docRoot}guide/topics/ui/declaring-layout.html">Layouts</a>.
318However, you must be aware that App Widget layouts are based on {@link
319android.widget.RemoteViews},
320which do not support every kind of layout or view widget.</p>
321
322<p>A RemoteViews object (and, consequently, an App Widget) can support the
323following layout classes:</p>
324
325<ul class="nolist">
326  <li>{@link android.widget.FrameLayout}</li>
327  <li>{@link android.widget.LinearLayout}</li>
328  <li>{@link android.widget.RelativeLayout}</li>
329  <li>{@link android.widget.GridLayout}</li>
330</ul>
331
332<p>And the following widget classes:</p>
333<ul class="nolist">
334  <li>{@link android.widget.AnalogClock}</li>
335  <li>{@link android.widget.Button}</li>
336  <li>{@link android.widget.Chronometer}</li>
337  <li>{@link android.widget.ImageButton}</li>
338  <li>{@link android.widget.ImageView}</li>
339  <li>{@link android.widget.ProgressBar}</li>
340  <li>{@link android.widget.TextView}</li>
341  <li>{@link android.widget.ViewFlipper}</li>
342  <li>{@link android.widget.ListView}</li>
343  <li>{@link android.widget.GridView}</li>
344  <li>{@link android.widget.StackView}</li>
345  <li>{@link android.widget.AdapterViewFlipper}</li>
346</ul>
347
348<p>Descendants of these classes are not supported.</p>
349
350<p>RemoteViews also supports {@link android.view.ViewStub}, which is an invisible, zero-sized View you can use
351to lazily inflate layout resources at runtime.</p>
352
353
354<h3 id="AddingMargins">Adding margins to App Widgets</h3>
355
356<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>
357
358<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>
359
360<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>
361
362<ol>
363  <li>Set your application's <code>targetSdkVersion</code> to 14 or greater.</li>
364  <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:
365
366<pre>
367&lt;FrameLayout
368  android:layout_width="match_parent"
369  android:layout_height="match_parent"
370  <strong>android:padding="@dimen/widget_margin"&gt;</strong>
371
372  &lt;LinearLayout
373    android:layout_width="match_parent"
374    android:layout_height="match_parent"
375    android:orientation="horizontal"
376    android:background="@drawable/my_widget_background"&gt;
377    &hellip;
378  &lt;/LinearLayout&gt;
379
380&lt;/FrameLayout&gt;
381</pre>
382
383  </li>
384  <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:
385
386    <p><strong>res/values/dimens.xml</strong>:<br>
387    <pre>&lt;dimen name="widget_margin"&gt;8dp&lt;/dimen&gt;</pre></p>
388
389    <p><strong>res/values-v14/dimens.xml</strong>:<br>
390    <pre>&lt;dimen name="widget_margin"&gt;0dp&lt;/dimen&gt;</pre></p>
391  </li>
392</ol>
393
394<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>
395
396
397<h2 id="AppWidgetProvider">Using the AppWidgetProvider Class</h2>
398
399<div class="sidebox-wrapper">
400<div class="sidebox">
401    <p>You must declare your AppWidgetProvider class implementation as a
402broadcast receiver
403    using the <code>&lt;receiver></code> element in the AndroidManifest (see
404    <a href="#Manifest">Declaring an App Widget in the Manifest</a> above).</p>
405  </div>
406</div>
407
408<p>The {@link android.appwidget.AppWidgetProvider} class extends
409BroadcastReceiver as a convenience
410class to handle the App Widget broadcasts. The AppWidgetProvider receives only
411the event broadcasts that
412are relevant to the App Widget, such as when the App Widget is updated, deleted,
413enabled, and disabled.
414When these broadcast events occur, the AppWidgetProvider receives the following
415method calls:</p>
416
417<dl>
418  <dt>
419  {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()}
420</dt>
421    <dd>This is called to update the App Widget at intervals defined by the
422<code>updatePeriodMillis</code>
423    attribute in the AppWidgetProviderInfo (see <a href="#MetaData">Adding the
424    AppWidgetProviderInfo Metadata</a> above). This method is also called
425    when the user adds the App Widget, so it should perform the essential setup,
426    such as define event handlers for Views and start a temporary
427    {@link android.app.Service}, if necessary. However, if you have declared a
428configuration
429    Activity, <strong>this method is not called</strong> when the user adds the
430App Widget,
431    but is called for the subsequent updates. It is the responsibility of the
432    configuration Activity to perform the first update when configuration is
433done.
434    (See <a href="#Configuring">Creating an App Widget Configuration
435Activity</a> below.)</dd>
436
437<dt>
438  {@link android.appwidget.AppWidgetProvider#onAppWidgetOptionsChanged onAppWidgetOptionsChanged()}
439</dt>
440<dd>
441This 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 />
442<ul>
443  <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_WIDTH}&mdash;Contains
444the lower bound on the current width, in dp units, of a widget instance.</li>
445  <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_HEIGHT}&mdash;Contains
446the lower bound on the current height, in dp units, of a widget instance.</li>
447  <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_WIDTH}&mdash;Contains
448 the upper bound on the current width, in dp units, of a widget instance.</li>
449  <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_HEIGHT}&mdash;Contains
450the upper bound on the current width, in dp units, of a widget instance.</li>
451</ul>
452
453This 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.
454</dd>
455  <dt>{@link android.appwidget.AppWidgetProvider#onDeleted(Context,int[])}</dt>
456    <dd>This is called every time an App Widget is deleted from the App Widget
457host.</dd>
458  <dt>{@link android.appwidget.AppWidgetProvider#onEnabled(Context)}</dt>
459    <dd>This is called when an instance the App Widget is created for the first
460time. For example, if the user
461    adds two instances of your App Widget, this is only called the first time.
462    If you need to open a new database or perform other setup that only needs to
463occur once
464    for all App Widget instances, then this is a good place to do it.</dd>
465  <dt>{@link android.appwidget.AppWidgetProvider#onDisabled(Context)}</dt>
466    <dd>This is called when the last instance of your App Widget is deleted from
467the App Widget host.
468    This is where you should clean up any work done in
469    {@link android.appwidget.AppWidgetProvider#onEnabled(Context)},
470    such as delete a temporary database.</dd>
471  <dt>{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)}</dt>
472    <dd>This is called for every broadcast and before each of the above callback
473methods.
474    You normally don't need to implement this method because the default
475AppWidgetProvider
476    implementation filters all App Widget broadcasts and calls the above
477    methods as appropriate.</dd>
478</dl>
479
480<p>The most important AppWidgetProvider callback is
481{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()}
482because it is called when
483each App Widget is added to a host (unless you use a configuration Activity). If
484your App Widget accepts any user interaction events, then you need to register
485the event handlers in this callback. If your App Widget doesn't create temporary
486files or databases, or perform other work that requires clean-up, then
487{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()}
488may be the only callback
489method you need to define. For example, if you want an App Widget with a button
490that launches an Activity when clicked, you could use the following
491implementation of AppWidgetProvider:</p>
492
493<pre>
494public class ExampleAppWidgetProvider extends AppWidgetProvider {
495
496    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
497        final int N = appWidgetIds.length;
498
499        // Perform this loop procedure for each App Widget that belongs to this provider
500        for (int i=0; i&lt;N; i++) {
501            int appWidgetId = appWidgetIds[i];
502
503            // Create an Intent to launch ExampleActivity
504            Intent intent = new Intent(context, ExampleActivity.class);
505            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
506
507            // Get the layout for the App Widget and attach an on-click listener
508            // to the button
509            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
510            views.setOnClickPendingIntent(R.id.button, pendingIntent);
511
512            // Tell the AppWidgetManager to perform an update on the current app widget
513            appWidgetManager.updateAppWidget(appWidgetId, views);
514        }
515    }
516}
517</pre>
518
519<p>This AppWidgetProvider defines only the
520{@link
521android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()}
522method for the purpose of
523defining a {@link android.app.PendingIntent} that launches an {@link
524android.app.Activity} and attaching it to the App Widget's button with {@link
525android.widget.RemoteViews#setOnClickPendingIntent(int,PendingIntent)}. Notice
526that it includes a loop that iterates through each entry in
527<code>appWidgetIds</code>, which is an array of IDs that identify each App
528Widget created by this provider. In this way, if the user creates more than one
529instance of the App Widget, then they are all updated simultaneously. However,
530only one <code>updatePeriodMillis</code> schedule will be managed for all
531instances of the App Widget. For example, if the update schedule is defined to
532be every two hours, and a second instance of the App Widget is added one hour
533after the first one, then they will both be updated on the period defined by the
534first one and the second update period will be ignored (they'll both be updated
535every two hours, not every hour).</p>
536
537<p class="note"><strong>Note:</strong> Because {@link
538android.appwidget.AppWidgetProvider} is an extension of {@link
539android.content.BroadcastReceiver}, your process is not guaranteed to keep
540running after the callback methods return (see {@link
541android.content.BroadcastReceiver} for information about the broadcast
542lifecycle). If your App Widget setup process can take several seconds (perhaps
543while performing web requests) and you require that your process continues,
544consider starting a {@link android.app.Service} in the
545{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()}
546method. From within the Service, you can perform your own updates
547to the App Widget without worrying about the AppWidgetProvider closing down due
548to an <a href="{@docRoot}guide/practices/responsiveness.html">Application
549Not Responding</a> (ANR) error. See the <a
550href="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
551android.app.Service}.</p>
552
553<p>Also see the <a
554href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.html">ExampleAppWidgetProvider.java</a>
555sample class.</p>
556
557
558<h3 id="ProviderBroadcasts">Receiving App Widget broadcast Intents</h3>
559
560<p>{@link android.appwidget.AppWidgetProvider} is just a convenience class.  If
561you would like
562to receive the App Widget broadcasts directly, you can implement your own
563{@link android.content.BroadcastReceiver} or override the
564{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)} callback.
565The Intents you need to care about are as follows:</p>
566<ul>
567  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE}</li>
568  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DELETED}</li>
569  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_ENABLED}</li>
570  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DISABLED}</li>
571  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_OPTIONS_CHANGED}</li>
572</ul>
573
574
575
576<h2 id="Configuring">Creating an App Widget Configuration Activity</h2>
577
578<p>If you would like the user to configure settings when he or she adds a new
579App Widget,
580you can create an App Widget configuration Activity. This {@link
581android.app.Activity}
582will be automatically launched by the App Widget host and allows the user to
583configure
584available settings for the App Widget at create-time, such as the App Widget
585color, size,
586update period or other functionality settings.</p>
587
588<p>The configuration Activity should be declared as a normal Activity in the
589Android manifest file.
590However, it will be launched by the App Widget host with the {@link
591android.appwidget.AppWidgetManager#ACTION_APPWIDGET_CONFIGURE
592ACTION_APPWIDGET_CONFIGURE} action,
593so the Activity needs to accept this Intent. For example:</p>
594
595<pre>
596&lt;activity android:name=".ExampleAppWidgetConfigure">
597    &lt;intent-filter>
598        &lt;action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
599    &lt;/intent-filter>
600&lt;/activity>
601</pre>
602
603<p>Also, the Activity must be declared in the AppWidgetProviderInfo XML file,
604with the
605<code>android:configure</code> attribute (see <a href="#MetaData">Adding
606the AppWidgetProviderInfo Metadata</a> above). For example, the configuration
607Activity
608can be declared like this:</p>
609
610<pre>
611&lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
612    ...
613    android:configure="com.example.android.ExampleAppWidgetConfigure"
614    ... >
615&lt;/appwidget-provider>
616</pre>
617
618<p>Notice that the Activity is declared with a fully-qualified namespace,
619because
620it will be referenced from outside your package scope.</p>
621
622<p>That's all you need to get started with a configuration Activity. Now all you
623need is the actual
624Activity. There are, however, two important things to remember when you
625implement the Activity:</p>
626<ul>
627  <li>The App Widget host calls the configuration Activity and the configuration
628Activity should always
629    return a result. The result should include the App Widget ID
630    passed by the Intent that launched the Activity (saved in the Intent extras
631as
632    {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID}).</li>
633  <li>The
634  {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()}
635    method <strong>will not be called</strong> when the App Widget
636is created
637    (the system will not send the ACTION_APPWIDGET_UPDATE broadcast when a
638configuration Activity
639    is launched). It is the responsibility of the configuration Activity to
640request an update from the
641    AppWidgetManager when the App Widget is first created. However,
642{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()}
643    will be called for subsequent updates&mdash;it is only skipped
644the first time.</li>
645</ul>
646
647<p>See the code snippets in the following section for an example of how to
648return a result
649from the configuration and update the App Widget.</p>
650
651
652<h3 id="UpdatingFromTheConfiguration">Updating the App Widget from the
653configuration Activity</h3>
654
655<p>When an App Widget uses a configuration Activity, it is the responsibility of
656the Activity
657to update the App Widget when configuration is complete.
658You can do so by requesting an update directly from the
659{@link android.appwidget.AppWidgetManager}.</p>
660
661<p>Here's a summary of the procedure to properly update the App Widget and close
662the configuration Activity:</p>
663
664<ol>
665  <li>First, get the App Widget ID from the Intent that launched the Activity:
666<pre>
667Intent intent = getIntent();
668Bundle extras = intent.getExtras();
669if (extras != null) {
670    mAppWidgetId = extras.getInt(
671            AppWidgetManager.EXTRA_APPWIDGET_ID,
672            AppWidgetManager.INVALID_APPWIDGET_ID);
673}
674</pre>
675  </li>
676  <li>Perform your App Widget configuration.</li>
677  <li>When the configuration is complete, get an instance of the
678AppWidgetManager by calling
679    {@link android.appwidget.AppWidgetManager#getInstance(Context)}:
680<pre>
681AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
682</pre>
683  </li>
684  <li>Update the App Widget with a {@link android.widget.RemoteViews} layout by
685calling
686    {@link android.appwidget.AppWidgetManager#updateAppWidget(int,RemoteViews)}:
687<pre>
688RemoteViews views = new RemoteViews(context.getPackageName(),
689R.layout.example_appwidget);
690appWidgetManager.updateAppWidget(mAppWidgetId, views);
691</pre>
692  </li>
693  <li>Finally, create the return Intent, set it with the Activity result, and
694finish the Activity:</li>
695<pre>
696Intent resultValue = new Intent();
697resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
698setResult(RESULT_OK, resultValue);
699finish();
700</pre>
701  </li>
702</ol>
703
704<p class="note"><strong>Tip:</strong> When your configuration Activity first
705opens, set
706the Activity result to RESULT_CANCELED. This way, if the user backs-out of the
707Activity before
708reaching the end, the App Widget host is notified that the configuration was
709cancelled and the
710App Widget will not be added.</p>
711
712<p>See the <a
713href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetConfigure.html">ExampleAppWidgetConfigure.java</a>
714sample class in ApiDemos for an example.</p>
715
716<h2 id="preview">Setting a Preview Image</h2>
717
718<p>Android 3.0 introduces the {@link
719
720
721android.appwidget.AppWidgetProviderInfo#previewImage} field, which specifies a
722preview of what the app widget looks like. This preview is shown to the user from the
723widget picker. If this field is not supplied, the app widget's icon is used for
724the preview.</p>
725
726<p>This is how you specify this setting in XML:</p>
727
728<pre>&lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
729  ...
730  android:previewImage="@drawable/preview">
731&lt;/appwidget-provider></pre>
732
733<p>To help create a preview image for your app widget (to specify in the {@link
734android.appwidget.AppWidgetProviderInfo#previewImage} field), the Android
735emulator includes an application called &quot;Widget Preview.&quot; To create a
736preview image, launch this application, select the app widget for your
737application and set it up how you'd like your preview image to appear, then save
738it and place it in your application's drawable resources.</p>
739
740<h2 id="lockscreen">Enabling App Widgets on the Lockscreen</h2>
741
742<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>
743
744<p>By default, every app widget supports placement on the Home screen, so "home_screen" is the default value for the
745{@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>
746<pre>
747&lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
748   ...
749   android:widgetCategory="keyguard|home_screen">
750&lt;/appwidget-provider>
751</pre>
752
753<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.
754
755You can detect whether your widget is on the lockscreen or home screen by calling
756{@link android.appwidget.AppWidgetManager#getAppWidgetOptions getAppWidgetOptions()}
757to get the widget's options as a {@link android.os.Bundle}. The returned bundle will include the key
758{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_HOST_CATEGORY}, whose value will be one of {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or
759{@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>
760
761<pre>
762AppWidgetManager appWidgetManager;
763int widgetId;
764Bundle myOptions = appWidgetManager.getAppWidgetOptions (widgetId);
765
766// Get the value of OPTION_APPWIDGET_HOST_CATEGORY
767int category = myOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
768
769// If the value is WIDGET_CATEGORY_KEYGUARD, it's a lockscreen widget
770boolean isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
771</pre>
772
773<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>
774
775<pre>
776int baseLayout = isKeyguard ? R.layout.keyguard_widget_layout : R.layout.widget_layout;
777</pre>
778
779
780<p>You should also specify an initial layout for your app widget when on the lock screen with the
781{@link android.appwidget.AppWidgetProviderInfo#initialKeyguardLayout android:initialKeyguardLayout} attribute. This works the same way as the
782{@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>
783
784<h3 id="lockscreen-sizing">Sizing guidelines</h3>
785
786<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>
787
788<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>
789
790<ul>
791    <li>If the widget does not mark itself as vertically resizable ({@code android:resizeMode="vertical"}), then the widget height will always be "small":
792      <ul>
793        <li>On a phone in portrait mode, "small" is defined as the space remaining when an unlock UI is being displayed.</li>
794        <li>On tablets and landscape phones, "small" is set on a per-device basis.</li>
795      </ul>
796    </li>
797    <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>
798</ul>
799
800<h2 id="collections">Using App Widgets with Collections</h2>
801
802<p>Android 3.0 introduces app widgets with collections. These kinds of App
803Widgets use the {@link android.widget.RemoteViewsService} to display collections
804that are backed by remote data, such as from a <a
805href="{@docRoot}guide/topics/providers/content-providers.html">content
806provider</a>. The data provided by the {@link android.widget.RemoteViewsService}
807is presented in the app widget using one of the following view types, which
808we’ll refer to as “collection views:”</p>
809
810<dl>
811  <dt>{@link android.widget.ListView}</dt>
812  <dd>A view that shows items in a
813vertically scrolling
814list. For an example, see the Gmail app widget. </dd>
815<dt>{@link android.widget.GridView}</dt>
816<dd>A view that shows items in
817two-dimensional scrolling grid. For an example, see the Bookmarks app
818widget.</dd>
819<dt>{@link android.widget.StackView}</dt>
820<dd>A
821stacked card view (kind of like a rolodex), where the user can flick the  front
822card up/down to see the previous/next card, respectively.  Examples include
823the YouTube and Books app widgets. </dd>
824<dt>{@link android.widget.AdapterViewFlipper}</dt>
825<dd>An adapter-backed simple
826{@link
827android.widget.ViewAnimator} that  animates between two or more views. Only one
828child is shown at a time.  </dd>
829</dl>
830
831<p>As stated above, these collection views display collections backed by remote
832data. This means that they use an {@link android.widget.Adapter} to bind their
833user interface to their data. An {@link android.widget.Adapter} binds individual
834items from a set of data into individual {@link android.view.View} objects.
835Because these collection views are backed by adapters, the Android framework
836must include extra architecture to support their use in app widgets. In the
837context of an app widget, the {@link android.widget.Adapter} is replaced by a
838{@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory},
839which is simply a thin wrapper around  the {@link android.widget.Adapter}
840interface.
841 When
842requested for a specific item in the collection, the {@link
843android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} creates
844and returns the item for the collection as a {@link android.widget.RemoteViews}
845object.
846In order to include a collection view in your app widget, you
847must implement {@link android.widget.RemoteViewsService} and {@link
848android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}.</p>
849
850<p> {@link android.widget.RemoteViewsService} is a service that allows a remote
851adapter to request {@link
852android.widget.RemoteViews} objects. {@link
853android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} is an
854interface for an adapter between a collection view (such as {@link
855android.widget.ListView}, {@link android.widget.GridView}, and so on) and the
856underlying data for that view. From the  <a
857href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
858sample</a>, here is an example of the boilerplate code you use to implement
859this service and interface:
860</p>
861
862<pre>
863public class StackWidgetService extends RemoteViewsService {
864    &#64;Override
865    public RemoteViewsFactory onGetViewFactory(Intent intent) {
866        return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
867    }
868}
869
870class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
871
872//... include adapter-like methods here. See the StackView Widget sample.
873
874}
875</pre>
876
877<h3 id="collection_sample">Sample application</h3>
878
879<p>The code excerpts in this section are drawn from the <a
880href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
881sample</a>:</p>
882
883<p>
884<img src="{@docRoot}images/appwidgets/StackWidget.png" alt="" />
885</p>
886
887<p>This sample consists of a stack of 10 views, which  display the values
888<code>&quot;0!&quot;</code> through <code>&quot;9!&quot;</code> The sample
889app widget has these primary behaviors:</p>
890
891<ul>
892
893  <li>The user can vertically fling the top view in the
894app widget to display the next or previous view. This is a built-in StackView
895behavior.</li>
896
897  <li>Without any user interaction, the app widget automatically advances
898through
899its views in sequence, like a slide show. This is due to the setting
900<code>android:autoAdvanceViewId=&quot;@id/stack_view&quot;</code> in the
901<code>res/xml/stackwidgetinfo.xml</code> file. This setting applies to the view
902ID,
903which in this case is the view ID of the stack view.</li>
904
905  <li>If the user touches the top view, the app widget displays the {@link
906android.widget.Toast} message &quot;Touched view <em>n</em>,&quot; where
907<em>n</em> is the index (position) of the touched view. For more discussion of
908how this is implemented, see
909<a href="#behavior">Adding behavior to individual items</a>.</li>
910
911</ul>
912<h3 id="implementing_collections">Implementing app widgets with collections</h3>
913
914<p>To implement an app widget with collections, you follow the same basic steps
915you would use to implement any app widget. The following sections  describe the
916additional steps you need to perform to implement an app widget with
917collections.</p>
918
919<h4>Manifest for app widgets with collections</h4>
920
921<p> In addition to the requirements listed in <a href="#Manifest">Declaring an
922app widget in the Manifest</a>, to make it possible for app widgets with
923collections to bind to your {@link android.widget.RemoteViewsService}, you must
924declare the service in your manifest file with the permission {@link
925android.Manifest.permission#BIND_REMOTEVIEWS}. This prevents other applications
926from freely accessing your app widget's data. For example, when creating an App
927Widget that uses {@link android.widget.RemoteViewsService} to populate a
928collection view, the manifest entry may look like this:</p>
929
930<pre>&lt;service android:name=&quot;MyWidgetService&quot;
931...
932android:permission=&quot;android.permission.BIND_REMOTEVIEWS&quot; /&gt;</pre>
933
934<p>The line <code>android:name=&quot;MyWidgetService&quot;</code>
935refers to your subclass of {@link android.widget.RemoteViewsService}. </p>
936
937<h4>Layout for app widgets with collections</h4>
938
939<p>The main requirement for your app widget layout XML file is that it
940include one of the collection views: {@link android.widget.ListView},
941{@link android.widget.GridView}, {@link android.widget.StackView}, or
942{@link android.widget.AdapterViewFlipper}. Here is the
943<code>widget_layout.xml</code> for
944the <a href="{@docRoot}resources/samples/StackWidget/index.html">StackView
945Widget sample</a>:</p>
946
947<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
948
949&lt;FrameLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
950    android:layout_width=&quot;match_parent&quot;
951    android:layout_height=&quot;match_parent&quot;&gt;
952    &lt;StackView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
953        android:id=&quot;&#64;+id/stack_view&quot;
954        android:layout_width=&quot;match_parent&quot;
955        android:layout_height=&quot;match_parent&quot;
956        android:gravity=&quot;center&quot;
957        android:loopViews=&quot;true&quot; /&gt;
958    &lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
959        android:id=&quot;&#64;+id/empty_view&quot;
960        android:layout_width=&quot;match_parent&quot;
961        android:layout_height=&quot;match_parent&quot;
962        android:gravity=&quot;center&quot;
963        android:background=&quot;&#64;drawable/widget_item_background&quot;
964        android:textColor=&quot;#ffffff&quot;
965        android:textStyle=&quot;bold&quot;
966        android:text=&quot;&#64;string/empty_view_text&quot;
967        android:textSize=&quot;20sp&quot; /&gt;
968&lt;/FrameLayout&gt;</pre>
969
970<p> Note that empty views must be siblings of the collection view for which the
971empty view represents empty state. </p>
972
973<p>In addition to the layout file for your entire app widget, you must create
974another layout file that defines the layout for each item in the collection (for
975example, a layout for each book in a collection of books). For example, the <a
976href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
977sample</a> only has one layout file, <code>widget_item.xml</code>, since all
978items use the same layout. But the <a
979href="{@docRoot}resources/samples/WeatherListWidget/index.html">
980WeatherListWidget sample</a> has two layout files:
981<code>dark_widget_item.xml</code> and <code>light_widget_item.xml</code>.</p>
982
983
984
985<h4 id="AppWidgetProvider-collections">AppWidgetProvider class for app widgets with collections</h4>
986
987<p>As with a regular app widget, the bulk of your code in your {@link
988android.appwidget.AppWidgetProvider} subclass typically goes in {@link
989android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
990android.appwidget.AppWidgetManager, int[]) onUpdate()}. The major difference in
991your implementation for {@link
992android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
993android.appwidget.AppWidgetManager, int[]) onUpdate()} when creating an app
994widget with collections is that you must call {@link
995android.widget.RemoteViews#setRemoteAdapter setRemoteAdapter()}. This tells the
996collection view where to get its data. The {@link
997android.widget.RemoteViewsService} can then return your implementation of {@link
998android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, and
999the widget can serve up the appropriate data. When you call this method, you
1000must pass an intent that  points to your implementation of {@link
1001android.widget.RemoteViewsService} and the app widget ID that specifies the app
1002widget to update.</p>
1003
1004
1005<p>For example, here's how the StackView Widget sample implements the {@link
1006android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
1007android.appwidget.AppWidgetManager, int[]) onUpdate()} callback method to set
1008the {@link
1009android.widget.RemoteViewsService} as the remote adapter for the app widget
1010collection:</p>
1011
1012<pre>public void onUpdate(Context context, AppWidgetManager appWidgetManager,
1013int[] appWidgetIds) {
1014    // update each of the app widgets with the remote adapter
1015    for (int i = 0; i &lt; appWidgetIds.length; ++i) {
1016
1017        // Set up the intent that starts the StackViewService, which will
1018        // provide the views for this collection.
1019        Intent intent = new Intent(context, StackWidgetService.class);
1020        // Add the app widget ID to the intent extras.
1021        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
1022        intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
1023        // Instantiate the RemoteViews object for the app widget layout.
1024        RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
1025        // Set up the RemoteViews object to use a RemoteViews adapter.
1026        // This adapter connects
1027        // to a RemoteViewsService  through the specified intent.
1028        // This is how you populate the data.
1029        rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
1030
1031        // The empty view is displayed when the collection has no items.
1032        // It should be in the same layout used to instantiate the RemoteViews
1033        // object above.
1034        rv.setEmptyView(R.id.stack_view, R.id.empty_view);
1035
1036        //
1037        // Do additional processing specific to this app widget...
1038        //
1039
1040        appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
1041    }
1042    super.onUpdate(context, appWidgetManager, appWidgetIds);
1043}</pre>
1044
1045<h4>RemoteViewsService class</h4>
1046
1047<div class="sidebox-wrapper">
1048<div class="sidebox">
1049<h3>Persisting data</h3>
1050   <p>You can’t rely on a single instance of your service, or any data it
1051contains, to persist. You should therefore not store any data in your {@link
1052android.widget.RemoteViewsService} (unless it is static). If you want your
1053app widget’s data to persist, the best approach is to use a {@link
1054android.content.ContentProvider} whose data persists beyond the process
1055lifecycle.</p> </div>
1056</div>
1057
1058<p>As described above, your {@link android.widget.RemoteViewsService} subclass
1059provides the {@link android.widget.RemoteViewsService.RemoteViewsFactory
1060RemoteViewsFactory} used to  populate the remote collection view.</p>
1061
1062<p>Specifically, you need to
1063perform these steps:</p>
1064
1065<ol>
1066  <li>Subclass {@link android.widget.RemoteViewsService}. {@link
1067android.widget.RemoteViewsService} is the service through which
1068a remote adapter can request {@link android.widget.RemoteViews}.  </li>
1069
1070  <li>In your {@link android.widget.RemoteViewsService} subclass, include a
1071class that implements the {@link
1072android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1073interface. {@link android.widget.RemoteViewsService.RemoteViewsFactory
1074RemoteViewsFactory} is an interface for an adapter between a remote collection
1075view (such as {@link android.widget.ListView}, {@link android.widget.GridView},
1076and so on) and  the underlying data for that view.  Your implementation is
1077responsible for making a {@link android.widget.RemoteViews} object  for each
1078item in the data set. This interface is a thin wrapper around {@link
1079android.widget.Adapter}.</li>
1080</ol>
1081
1082<p>The primary contents of the {@link android.widget.RemoteViewsService}
1083implementation is its {@link
1084android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory},
1085described below.</p>
1086
1087<h4>RemoteViewsFactory interface</h4>
1088
1089<p>Your custom class that implements the {@link
1090android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1091interface provides the app widget with the data for the items in its collection.
1092To
1093do this, it combines your app widget item XML layout file with a source of data.
1094This source of data could be anything from a database to a simple array. In the
1095<a href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1096sample</a>, the data source is an array of <code>WidgetItems</code>. The {@link
1097android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1098functions as an adapter to glue the data to the remote collection view.</p>
1099
1100<p>The two most important methods you need to implement for your
1101
1102{@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1103subclass are
1104{@link android.widget.RemoteViewsService.RemoteViewsFactory#onCreate()
1105onCreate()} and
1106{@link android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int)
1107getViewAt()}
1108.</p>
1109
1110<p>The system calls {@link
1111android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} when
1112creating your factory for the first time. This is where you set up any
1113connections and/or cursors to your data source. For example, the <a
1114href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1115sample</a> uses {@link
1116android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} to
1117initialize an array of <code>WidgetItem</code> objects. When your app widget is
1118active, the system accesses these objects using their index position in the
1119array and the text they contain is displayed  </p>
1120
1121<p>Here is an excerpt from the <a
1122href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget</a>
1123sample's
1124{@link android.widget.RemoteViewsService.RemoteViewsFactory
1125RemoteViewsFactory} implementation that shows portions of the {@link
1126android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()}
1127method:</p>
1128
1129<pre>class StackRemoteViewsFactory implements
1130RemoteViewsService.RemoteViewsFactory {
1131    private static final int mCount = 10;
1132    private List&lt;WidgetItem&gt; mWidgetItems = new ArrayList&lt;WidgetItem&gt;();
1133    private Context mContext;
1134    private int mAppWidgetId;
1135
1136    public StackRemoteViewsFactory(Context context, Intent intent) {
1137        mContext = context;
1138        mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1139                AppWidgetManager.INVALID_APPWIDGET_ID);
1140    }
1141
1142    public void onCreate() {
1143        // In onCreate() you setup any connections / cursors to your data source. Heavy lifting,
1144        // for example downloading or creating content etc, should be deferred to onDataSetChanged()
1145        // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
1146        for (int i = 0; i &lt; mCount; i++) {
1147            mWidgetItems.add(new WidgetItem(i + &quot;!&quot;));
1148        }
1149        ...
1150    }
1151...</pre>
1152
1153<p>The {@link android.widget.RemoteViewsService.RemoteViewsFactory
1154RemoteViewsFactory} method {@link
1155android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()}
1156returns a {@link android.widget.RemoteViews} object corresponding to the data at
1157the specified <code>position</code> in the data set. Here is an excerpt from
1158the <a
1159href="http://developer.android.com/resources/samples/StackWidget/index.html">
1160StackView Widget</a> sample's {@link
1161android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
1162implementation:</p>
1163
1164<pre>public RemoteViews getViewAt(int position) {
1165
1166    // Construct a remote views item based on the app widget item XML file,
1167    // and set the text based on the position.
1168    RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
1169    rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
1170
1171    ...
1172    // Return the remote views object.
1173    return rv;
1174}</pre>
1175
1176<h4 id="behavior">Adding behavior to individual items</h4>
1177
1178<p>The above sections show you how to bind your data to your app widget
1179collection. But what if you want to add dynamic behavior to the individual items
1180in your collection view?</p>
1181
1182<p> As described in <a href="#AppWidgetProvider">Using the AppWidgetProvider
1183Class</a>, you  normally use {@link
1184android.widget.RemoteViews#setOnClickPendingIntent(int,
1185android.app.PendingIntent) setOnClickPendingIntent()} to set an object's click
1186behavior&mdash;such as to cause a button to launch an {@link
1187android.app.Activity}. But this approach is not allowed for child views in an
1188individual collection item (to clarify, you could use {@link
1189android.widget.RemoteViews#setOnClickPendingIntent(int,
1190android.app.PendingIntent) setOnClickPendingIntent()} to set up a global button
1191in the Gmail app widget that launches the app, for example, but not on the
1192individual list items). Instead, to add click behavior to individual items in a
1193collection, you  use {@link
1194android.widget.RemoteViews#setOnClickFillInIntent(int, android.content.Intent)
1195setOnClickFillInIntent()}. This entails setting up up a pending intent template
1196for your collection view, and then setting a fill-in intent on each item in the
1197collection via your {@link android.widget.RemoteViewsService.RemoteViewsFactory
1198RemoteViewsFactory}.</p>
1199<p>This section uses the <a
1200href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1201sample</a> to describe how to add behavior to individual items. In the <a
1202href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1203sample</a>, if the user touches the top view, the app widget displays the {@link
1204android.widget.Toast} message &quot;Touched view <em>n</em>,&quot; where
1205<em>n</em> is the index (position) of the touched view. This is how it
1206works:</p>
1207
1208<ul>
1209  <li>The <code>StackWidgetProvider</code> (an {@link
1210android.appwidget.AppWidgetProvider} subclass) creates a pending intent that has
1211a custom action called <code>TOAST_ACTION</code>.</li>
1212  <li>When the user touches a view, the intent is fired and it broadcasts
1213<code>TOAST_ACTION</code>.</li>
1214
1215  <li>This broadcast is intercepted by the <code>StackWidgetProvider</code>'s
1216{@link android.appwidget.AppWidgetProvider#onReceive(android.content.Context,
1217android.content.Intent) onReceive()} method, and the app widget displays the
1218{@link
1219android.widget.Toast} message for the touched view. The data for the collection
1220items is provided by the {@link
1221android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, via
1222the {@link android.widget.RemoteViewsService}.</li>
1223</ul>
1224
1225<p class="note"><strong>Note:</strong> The <a
1226href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
1227sample</a> uses a broadcast, but typically an app widget would simply launch an
1228activity in a scenario like this one.</p>
1229
1230<h5>Setting up the pending intent template</h5>
1231
1232<p>The <code>StackWidgetProvider</code> ({@link
1233android.appwidget.AppWidgetProvider} subclass) sets up a pending intent.
1234Individuals items of a collection cannot set up their own pending intents.
1235Instead, the collection as a whole sets up a pending intent template, and the
1236individual items set a fill-in intent to create unique behavior on an
1237item-by-item
1238basis.</p>
1239
1240<p>This class  also receives the broadcast that is sent when the user touches a
1241view. It processes this event in its {@link
1242android.appwidget.AppWidgetProvider#onReceive(android.content.Context,
1243android.content.Intent) onReceive()} method. If the intent's action is
1244<code>TOAST_ACTION</code>, the app widget displays a {@link
1245android.widget.Toast}
1246message for the current view.</p>
1247
1248<pre>public class StackWidgetProvider extends AppWidgetProvider {
1249    public static final String TOAST_ACTION = &quot;com.example.android.stackwidget.TOAST_ACTION&quot;;
1250    public static final String EXTRA_ITEM = &quot;com.example.android.stackwidget.EXTRA_ITEM&quot;;
1251
1252    ...
1253
1254    // Called when the BroadcastReceiver receives an Intent broadcast.
1255    // Checks to see whether the intent's action is TOAST_ACTION. If it is, the app widget
1256    // displays a Toast message for the current item.
1257    &#64;Override
1258    public void onReceive(Context context, Intent intent) {
1259        AppWidgetManager mgr = AppWidgetManager.getInstance(context);
1260        if (intent.getAction().equals(TOAST_ACTION)) {
1261            int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1262                AppWidgetManager.INVALID_APPWIDGET_ID);
1263            int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0);
1264            Toast.makeText(context, &quot;Touched view &quot; + viewIndex, Toast.LENGTH_SHORT).show();
1265        }
1266        super.onReceive(context, intent);
1267    }
1268
1269    &#64;Override
1270    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
1271        // update each of the app widgets with the remote adapter
1272        for (int i = 0; i &lt; appWidgetIds.length; ++i) {
1273
1274            // Sets up the intent that points to the StackViewService that will
1275            // provide the views for this collection.
1276            Intent intent = new Intent(context, StackWidgetService.class);
1277            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
1278            // When intents are compared, the extras are ignored, so we need to embed the extras
1279            // into the data so that the extras will not be ignored.
1280            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
1281            RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
1282            rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
1283
1284            // The empty view is displayed when the collection has no items. It should be a sibling
1285            // of the collection view.
1286            rv.setEmptyView(R.id.stack_view, R.id.empty_view);
1287
1288            // This section makes it possible for items to have individualized behavior.
1289            // It does this by setting up a pending intent template. Individuals items of a collection
1290            // cannot set up their own pending intents. Instead, the collection as a whole sets
1291            // up a pending intent template, and the individual items set a fillInIntent
1292            // to create unique behavior on an item-by-item basis.
1293            Intent toastIntent = new Intent(context, StackWidgetProvider.class);
1294            // Set the action for the intent.
1295            // When the user touches a particular view, it will have the effect of
1296            // broadcasting TOAST_ACTION.
1297            toastIntent.setAction(StackWidgetProvider.TOAST_ACTION);
1298            toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
1299            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
1300            PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
1301                PendingIntent.FLAG_UPDATE_CURRENT);
1302            rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent);
1303
1304            appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
1305        }
1306    super.onUpdate(context, appWidgetManager, appWidgetIds);
1307    }
1308}</pre>
1309
1310<h5><strong>Setting the fill-in Intent</strong></h5>
1311
1312<p>Your {@link android.widget.RemoteViewsService.RemoteViewsFactory
1313RemoteViewsFactory} must set a fill-in intent on each item in the collection.
1314This makes it possible to distinguish the individual on-click action of a given
1315item. The fill-in intent is then combined with the {@link
1316android.app.PendingIntent} template in order to determine the final intent that
1317will be executed when the item is clicked. </p>
1318
1319<pre>
1320public class StackWidgetService extends RemoteViewsService {
1321    &#64;Override
1322    public RemoteViewsFactory onGetViewFactory(Intent intent) {
1323        return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
1324    }
1325}
1326
1327class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
1328    private static final int mCount = 10;
1329    private List&lt;WidgetItem&gt; mWidgetItems = new ArrayList&lt;WidgetItem&gt;();
1330    private Context mContext;
1331    private int mAppWidgetId;
1332
1333    public StackRemoteViewsFactory(Context context, Intent intent) {
1334        mContext = context;
1335        mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1336                AppWidgetManager.INVALID_APPWIDGET_ID);
1337    }
1338
1339    // Initialize the data set.
1340        public void onCreate() {
1341            // In onCreate() you set up any connections / cursors to your data source. Heavy lifting,
1342            // for example downloading or creating content etc, should be deferred to onDataSetChanged()
1343            // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
1344            for (int i = 0; i &lt; mCount; i++) {
1345                mWidgetItems.add(new WidgetItem(i + &quot;!&quot;));
1346            }
1347           ...
1348        }
1349        ...
1350
1351        // Given the position (index) of a WidgetItem in the array, use the item's text value in
1352        // combination with the app widget item XML file to construct a RemoteViews object.
1353        public RemoteViews getViewAt(int position) {
1354            // position will always range from 0 to getCount() - 1.
1355
1356            // Construct a RemoteViews item based on the app widget item XML file, and set the
1357            // text based on the position.
1358            RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
1359            rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
1360
1361            // Next, set a fill-intent, which will be used to fill in the pending intent template
1362            // that is set on the collection view in StackWidgetProvider.
1363            Bundle extras = new Bundle();
1364            extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
1365            Intent fillInIntent = new Intent();
1366            fillInIntent.putExtras(extras);
1367            // Make it possible to distinguish the individual on-click
1368            // action of a given item
1369            rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
1370
1371            ...
1372
1373            // Return the RemoteViews object.
1374            return rv;
1375        }
1376    ...
1377    }</pre>
1378
1379<h3 id="fresh">Keeping Collection Data Fresh</h3>
1380
1381<p>The following figure illustrates the flow that occurs in an app widget that
1382uses
1383collections when updates occur. It shows how the app widget code interacts with
1384the  {@link android.widget.RemoteViewsService.RemoteViewsFactory
1385RemoteViewsFactory}, and how you can trigger updates:</p>
1386
1387<img src="{@docRoot}images/appwidgets/appwidget_collections.png" alt="" />
1388
1389<p>One feature of app widgets that use collections is the ability to provide
1390users with up-to-date content. For example, consider the Android 3.0 Gmail
1391app widget, which provides users with a snapshot of their inbox. To make this
1392possible, you need to be able to trigger your {@link
1393android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} and
1394collection view to fetch and display new data. You achieve this with the {@link
1395android.appwidget.AppWidgetManager} call {@link
1396android.appwidget.AppWidgetManager#notifyAppWidgetViewDataChanged(int, int)
1397notifyAppWidgetViewDataChanged()}. This call results in a callback to your
1398<code>RemoteViewsFactory</code>’s {@link
1399android.widget.RemoteViewsService.RemoteViewsFactory#onDataSetChanged()
1400onDataSetChanged()} method, which gives you the opportunity to fetch any new
1401data. Note that you can perform
1402processing-intensive operations synchronously within the  {@link
1403android.widget.RemoteViewsService.RemoteViewsFactory#onDataSetChanged()
1404onDataSetChanged()} callback. You are guaranteed that this call will be
1405completed before the metadata or view data is fetched from the {@link
1406android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}. In
1407addition, you can perform processing-intensive operations within the {@link
1408android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()}
1409method. If this call takes a long time, the loading view (specified by the
1410<code>RemoteViewsFactory</code>’s  {@link
1411android.widget.RemoteViewsService.RemoteViewsFactory#getLoadingView()} method)
1412will be displayed in the corresponding position of the collection view until it
1413returns.</p>
1414
1415
1416