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<receiver android:name="ExampleAppWidgetProvider" > 117 <intent-filter> 118 <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> 119 </intent-filter> 120 <meta-data android:name="android.appwidget.provider" 121 android:resource="@xml/example_appwidget_info" /> 122</receiver> 123</pre> 124 125<p>The <code><receiver></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><intent-filter></code> element must include an 131<code><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><meta-data></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><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<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</appwidget-provider> 181</pre> 182 183<p>Here's a summary of the <code><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—perhaps no more than once an hour to 221conserve the battery. You might also allow the user to adjust the frequency in a 222configuration—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><receiver></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—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><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<FrameLayout 368 android:layout_width="match_parent" 369 android:layout_height="match_parent" 370 <strong>android:padding="@dimen/widget_margin"></strong> 371 372 <LinearLayout 373 android:layout_width="match_parent" 374 android:layout_height="match_parent" 375 android:orientation="horizontal" 376 android:background="@drawable/my_widget_background"> 377 … 378 </LinearLayout> 379 380</FrameLayout> 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><dimen name="widget_margin">8dp</dimen></pre></p> 388 389 <p><strong>res/values-v14/dimens.xml</strong>:<br> 390 <pre><dimen name="widget_margin">0dp</dimen></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><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}—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}—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}—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}—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<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<activity android:name=".ExampleAppWidgetConfigure"> 597 <intent-filter> 598 <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/> 599 </intent-filter> 600</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<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 612 ... 613 android:configure="com.example.android.ExampleAppWidgetConfigure" 614 ... > 615</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—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><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 729 ... 730 android:previewImage="@drawable/preview"> 731</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 "Widget Preview." 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<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 748 ... 749 android:widgetCategory="keyguard|home_screen"> 750</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 @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>"0!"</code> through <code>"9!"</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="@id/stack_view"</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 "Touched view <em>n</em>," 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><service android:name="MyWidgetService" 931... 932android:permission="android.permission.BIND_REMOTEVIEWS" /></pre> 933 934<p>The line <code>android:name="MyWidgetService"</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><?xml version="1.0" encoding="utf-8"?> 948 949<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 950 android:layout_width="match_parent" 951 android:layout_height="match_parent"> 952 <StackView xmlns:android="http://schemas.android.com/apk/res/android" 953 android:id="@+id/stack_view" 954 android:layout_width="match_parent" 955 android:layout_height="match_parent" 956 android:gravity="center" 957 android:loopViews="true" /> 958 <TextView xmlns:android="http://schemas.android.com/apk/res/android" 959 android:id="@+id/empty_view" 960 android:layout_width="match_parent" 961 android:layout_height="match_parent" 962 android:gravity="center" 963 android:background="@drawable/widget_item_background" 964 android:textColor="#ffffff" 965 android:textStyle="bold" 966 android:text="@string/empty_view_text" 967 android:textSize="20sp" /> 968</FrameLayout></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 < 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<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>(); 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 < mCount; i++) { 1147 mWidgetItems.add(new WidgetItem(i + "!")); 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—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 "Touched view <em>n</em>," 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 = "com.example.android.stackwidget.TOAST_ACTION"; 1250 public static final String EXTRA_ITEM = "com.example.android.stackwidget.EXTRA_ITEM"; 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 @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, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show(); 1265 } 1266 super.onReceive(context, intent); 1267 } 1268 1269 @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 < 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 @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<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>(); 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 < mCount; i++) { 1345 mWidgetItems.add(new WidgetItem(i + "!")); 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