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