Home | History | Annotate | Download | only in appwidgets
      1 page.title=App Widget Host
      2 page.tags=AppWidgetHost,home screen,launcher
      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="#host-binding">Binding App Widgets</a>
     11           <ol>
     12             <li><a href="#binding-pre">Binding app widgets on Android 4.0 and lower</a></li>
     13             <li><a href="#binding-41">Binding app widgets on Android 4.1 and higher</a></li>
     14          </ol>
     15           </li>
     16           <li><a href="#host-state">Host Responsibilities</a>
     17           <ol>
     18             <li><a href="#30">Android 3.0</a></li>
     19             <li><a href="#31">Android 3.1</a></li>
     20             <li><a href="#40">Android 4.0</a></li>
     21             <li><a href="#41">Android 4.1</li>
     22             <li><a href="#42">Android 4.2</a></li>
     23          </ol>
     24          </li>
     25       </ol>
     26   </div>
     27 </div>
     28 
     29 
     30 <p>The Android Home screen available on most Android devices allows the user
     31 to embed <a href="{@docRoot}guide/topics/appwidgets/index.html">app widgets</a> for quick
     32 access to content. If you're building a Home replacement or a similar app,
     33 you can also allow the user to embed app widgets by implementing an
     34 {@link android.appwidget.AppWidgetHost}.
     35 This is not something that most apps will ever need to do, but if you are 
     36 creating your own host, it's important to understand the contractual obligations 
     37 a host implicitly agrees to.</p>
     38 
     39 <p>This document focuses on the responsibilities involved in implementing a custom 
     40 {@link android.appwidget.AppWidgetHost}. For an example of how to implement an 
     41 {@link android.appwidget.AppWidgetHost}, see the source code for the
     42 Android Home screen 
     43 <a href="https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/Launcher.java">
     44 Launcher</a>. 
     45 
     46 
     47 <p>Here is an overview of key classes and concepts involved in implementing a custom 
     48 {@link android.appwidget.AppWidgetHost}:</p>
     49 <ul>
     50     <li><strong>App Widget Host</strong>&mdash;  
     51     The {@link android.appwidget.AppWidgetHost} provides the interaction 
     52 with the AppWidget service for apps, like the home screen, that want to embed 
     53 app widgets in their UI. An {@link android.appwidget.AppWidgetHost} must have 
     54 an ID that is unique within the host's own package. This ID remains persistent 
     55 across all uses of the host. The ID is typically a hard-coded value that you assign
     56 in your application.</li>
     57   
     58     <li><strong>App Widget ID</strong>&mdash;
     59     Each app widget instance is assigned a unique ID at the time of binding 
     60 (see {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()}, 
     61 discussed in more detail in <a href="#binding">Binding app widgets</a>). 
     62 The unique ID is obtained by the host using {@link android.appwidget.AppWidgetHost#allocateAppWidgetId() allocateAppWidgetId()}. This ID is persistent across the lifetime of the widget, 
     63 that is, until it is deleted from the host. Any host-specific state (such as the 
     64 size and location of the widget) should be persisted by the hosting package and 
     65 associated with the app widget ID.
     66 </li>
     67   
     68     <li><strong>App Widget Host View</strong>&mdash;  
     69     {@link android.appwidget.AppWidgetHostView} can be thought of as a frame 
     70 that the widget is wrapped in whenever it needs to be displayed. An app widget 
     71 is assigned to an {@link android.appwidget.AppWidgetHostView} every time the 
     72 widget is inflated by the host. </li>
     73     <li><strong>Options Bundle</strong>&mdash;
     74 The {@link android.appwidget.AppWidgetHost} uses the options bundle to communicate 
     75 information to the {@link android.appwidget.AppWidgetProvider} about how the 
     76 widget is being displayed (for example, size range, and whether the widget is on 
     77 a lockscreen or the home screen). This information allows the 
     78 {@link android.appwidget.AppWidgetProvider} to tailor the widget's contents 
     79 and appearance based on how and where it is  displayed.
     80 You use 
     81 {@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions(android.os.Bundle) updateAppWidgetOptions()}
     82 and 
     83 {@link android.appwidget.AppWidgetHostView#updateAppWidgetSize updateAppWidgetSize()}
     84 
     85 to modify an app widget's 
     86 bundle. Both of these methods trigger a callback to the 
     87 {@link android.appwidget.AppWidgetProvider}.</p></li>
     88 </ul>
     89 
     90 <h2 id="host-binding">Binding App Widgets</h2>
     91 
     92 <p>When a user adds an app widget to a host, a process called
     93 <em>binding</em> occurs. <em>Binding</em> refers to associating
     94 a particular app widget ID to a specific host and to a specific
     95 {@link android.appwidget.AppWidgetProvider}. There are different
     96 ways of achieving this, depending on what version of Android your
     97 app is running on.</p>
     98 
     99 <h3 id="binding-pre">Binding app widgets on Android 4.0 and lower</h3>
    100 
    101 <p>On devices running Android version 4.0 and lower, users add app widgets 
    102 via a system activity that allows users to select a widget. This implicitly 
    103 does a permission check&mdash;that is, by adding the app widget, the user is 
    104 implicitly granting permission to your app to add app widgets to the host. 
    105 Here is an example that illustrates 
    106 this approach, taken from the original 
    107 <a href="https://android.googlesource.com/platform/packages/apps/Launcher/+/master/src/com/android/launcher/Launcher.java">Launcher</a>. In this snippet, an event handler invokes 
    108 {@link android.app.Activity#startActivityForResult(android.content.Intent,int) startActivityForResult()} 
    109 with the request code {@code REQUEST_PICK_APPWIDGET} in response to a 
    110 user action:</p>
    111 
    112 <pre>
    113 private static final int REQUEST_CREATE_APPWIDGET = 5;
    114 private static final int REQUEST_PICK_APPWIDGET = 9;
    115 ...
    116 public void onClick(DialogInterface dialog, int which) {
    117     switch (which) {
    118     ...
    119         case AddAdapter.ITEM_APPWIDGET: {
    120             ...
    121             int appWidgetId = 
    122                     Launcher.this.mAppWidgetHost.allocateAppWidgetId();
    123             Intent pickIntent = 
    124                     new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
    125             pickIntent.putExtra
    126                     (AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    127             ...
    128             startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
    129             break;
    130     }
    131     ...
    132 }</pre>
    133 
    134 <p>When the system activity finishes, it returns a result with the user's chosen
    135 app widget to your activity. In the following example, the activity responds
    136 by calling {@code addAppWidget()} to add the app widget:</p>
    137 
    138 <pre>public final class Launcher extends Activity 
    139         implements View.OnClickListener, OnLongClickListener {
    140     ...
    141     &#64;Override
    142     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    143         mWaitingForResult = false;
    144 
    145         if (resultCode == RESULT_OK && mAddItemCellInfo != null) {
    146             switch (requestCode) {
    147                 ...
    148                 case REQUEST_PICK_APPWIDGET:
    149                     addAppWidget(data);
    150                     break;
    151                 case REQUEST_CREATE_APPWIDGET:
    152                     completeAddAppWidget(data, mAddItemCellInfo, !mDesktopLocked);
    153                     break;
    154                 }
    155         } 
    156         ...
    157     }
    158 }</pre>
    159 
    160 <p>The method {@code addAppWidget()} checks to see if the app widget
    161 needs to be configured before it's added:</p>
    162 
    163 <pre>void addAppWidget(Intent data) {
    164     int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
    165 
    166     String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET);
    167     AppWidgetProviderInfo appWidget = 
    168             mAppWidgetManager.getAppWidgetInfo(appWidgetId);
    169 
    170     if (appWidget.configure != null) {
    171         // Launch over to configure widget, if needed.
    172         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
    173         intent.setComponent(appWidget.configure);
    174         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    175         startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);
    176     } else {
    177         // Otherwise, finish adding the widget.
    178     }
    179 }</pre>
    180 
    181 <p>For more discussion of configuration,
    182 see <a href="{@docRoot}guide/topics/appwidgets/index.html#Configuring">Creating an
    183 App Widget Configuration Activity</a>.</p>
    184 
    185 <p>Once the app widget is ready, the next step is to do the
    186 actual work of adding it to the workspace. The 
    187 <a href="https://android.googlesource.com/platform/packages/apps/Launcher/+/master/src/com/android/launcher/Launcher.java">original Launcher</a> uses a method called {@code completeAddAppWidget()}
    188 to do this.</p>
    189 
    190 <h3 id="binding-41">Binding app widgets on Android 4.1 and higher</h3>
    191 
    192 <p>Android 4.1 adds APIs for a more streamlined binding process.
    193 These APIs also make it possible for a host to provide a custom UI for
    194 binding. To use this improved process, your app must declare the
    195 {@link android.Manifest.permission#BIND_APPWIDGET} permission in its manifest:</p>
    196 
    197 <pre>&lt;uses-permission android:name="android.permission.BIND_APPWIDGET" /&gt;
    198 </pre>
    199 
    200 
    201 <p>But this is just the first step. At runtime the user must
    202 explicitly grant permission to your app to allow it to add app widgets
    203 to the host. To test whether your app has permission to add the widget,
    204 you use the 
    205 {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()} 
    206 method. 
    207 If {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()}
    208 returns {@code false}, your app must display a dialog prompting the
    209 user to grant permission 
    210 ("allow" or "always allow," to cover all future app widget additions).
    211 This snippet gives an example of how to display the dialog:</p>
    212 
    213 <pre>Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
    214 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    215 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
    216 // This is the options bundle discussed above
    217 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
    218 startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
    219 </pre>
    220 
    221 <p>The host also has to check whether the user added 
    222 an app widget that needs configuration. For more discussion of this topic,
    223 see 
    224 <a href="{@docRoot}guide/topics/appwidgets/index.html#Configuring">Creating
    225 an App Widget Configuration Activity</a>.</p>
    226 
    227 <h2 id="host-state">Host Responsibilities</h2>
    228 
    229 <div class="sidebox-wrapper">
    230 <div class="sidebox">
    231   <h2>What Version are You Targeting?</h2>
    232   <p>The approach you use in implementing your host should depend on what Android version  
    233 you're targeting. Many of the features described in this section were introduced 
    234 in 3.0 or later. For example:</p>
    235 <ul>
    236 <li>Android 3.0 (API Level 11) introduces auto-advance behavior for widgets.</li>
    237 <li>Android 3.1 (API Level 12) introduces the ability to resize widgets.</li>
    238 <li>Android 4.0 (API Level 15) introduces a change in padding policy that
    239 puts the responsibility on the 
    240 host to manage padding.</li>
    241 <li>Android 4.1 (API Level 16) adds an API that allows the widget provider
    242 to get more detailed information about the environment in which its
    243 widget instances are being hosted.</li>
    244 <li>Android 4.2 (API Level 17) introduces the options bundle and the 
    245 {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int,android.content.ComponentName,android.os.Bundle) bindAppWidgetIdIfAllowed()} 
    246 method. It also introduces lockscreen widgets.</li>
    247 </ul>
    248 <p>If you are targeting earlier devices, refer to the original 
    249 <a href="https://android.googlesource.com/platform/packages/apps/Launcher/+/master/src/com/android/launcher/Launcher.java">Launcher</a> as an example.
    250 </div>
    251 </div>
    252 
    253 <p>Widget developers can specify a number of configuration settings
    254 for widgets using the <a href="{@docRoot}guide/topics/appwidgets/index.html#MetaData">
    255 AppWidgetProviderInfo metadata</a>.
    256 These configuration options, discussed in more detail below, can be
    257 retrieved by the host from the {@link android.appwidget.AppWidgetProviderInfo}
    258 object associated with a widget provider.</p>
    259 
    260 <p>Regardless of the version of Android you are targeting, all hosts
    261 have the following responsibilities:</p>
    262 
    263 <ul>
    264 <li>When adding a widget, you must allocate the widget ID as described above.
    265 You must also make sure that when a widget is removed from the host, you call {@link android.appwidget.AppWidgetHost#deleteAppWidgetId deleteAppWidgetId()}
    266 to deallocate the widget ID.</li>
    267 
    268 <li>When adding a widget, be sure to launch its configuration activity
    269 if it exists, as described in
    270 <a href="{@docRoot}guide/topics/appwidgets/index.html#UpdatingFromTheConfiguration">
    271 Updating the App Widget
    272 from the Configuration Activity</a>. This is a necessary step for many app widgets before
    273 they can be properly displayed.</li>
    274 
    275 <li>Every app widget specifies a minimum width and height in dps, as defined in the {@link android.appwidget.AppWidgetProviderInfo} metadata
    276 (using {@link android.appwidget.AppWidgetProviderInfo#minWidth android:minWidth} and 
    277 {@link android.appwidget.AppWidgetProviderInfo#minHeight android:minHeight}).
    278 Make sure that the widget is laid out with at least this many dps.
    279 For example, many hosts align icons and widgets in a grid. In this scenario,
    280 by default the host should add the app widget using the minimum number of
    281 cells that satisfy the {@code minWidth} and {@code minHeight} constraints.</li>
    282 
    283 </ul>
    284 
    285 <p>In addition to the requirements listed above, specific platform
    286 versions introduce features that place new responsibilities on the
    287 host. These are described in the following sections.</p>
    288 
    289 <h3 id="30">Android 3.0</h3>
    290 
    291 <p>Android 3.0 (API Level 11) introduces the ability for a widget to specify {@link android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId autoAdvanceViewId()}.
    292 This view ID should point to an instance of an
    293 {@link android.widget.Advanceable}, such as {@link android.widget.StackView}
    294 or {@link android.widget.AdapterViewFlipper}. This indicates that the host
    295 should call {@link android.widget.Advanceable#advance advance()} on this
    296 view at an interval deemed appropriate by the host (taking into account whether
    297 it makes sense to advance the widget&mdash;for example, the host probably
    298 wouldn't want to advance a widget if it were on another page, or
    299 if the screen were turned off).</p>
    300 
    301 <h3 id="31">Android 3.1</h3>
    302 
    303 <p>Android 3.1 (API Level 12) introduces the ability to resize widgets.
    304 A widget can specify that it is resizable using the
    305 {@link android.appwidget.AppWidgetProviderInfo#resizeMode android:resizeMode}
    306 attribute in the {@link android.appwidget.AppWidgetProviderInfo}
    307 metadata, and indicate whether it supports horizontal and/or
    308 vertical resizing. Introduced in Android 4.0 (API Level 14), the widget can also specify a
    309 {@link android.appwidget.AppWidgetProviderInfo#minResizeWidth android:minResizeWidth}
    310 and/or {@link android.appwidget.AppWidgetProviderInfo#minResizeHeight android:minResizeHeight}.</p>
    311 
    312 <p>It is the hosts responsibility to make it possible for the
    313 widget to be resized horizontally and/or vertically, as specified
    314 by the widget. A widget that specifies that it is resizable can be
    315 resized arbitrarily large, but should not be resized smaller than
    316 the values specified by {@link
    317 android.appwidget.AppWidgetProviderInfo#minResizeWidth android:minResizeWidth}
    318 and {@link
    319 android.appwidget.AppWidgetProviderInfo#minResizeHeight android:minResizeHeight}.
    320 For a sample implementation, see  <a href="https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/AppWidgetResizeFrame.java">
    321 {@code AppWidgetResizeFrame}</a> in {@code Launcher2}.</p>
    322 
    323 
    324 <h3 id="40">Android 4.0</h3>
    325 
    326 <p>Android 4.0 (API Level 15) introduces a change in padding policy that
    327 puts the responsibility on the host to manage padding. As of 4.0, app
    328 widgets no longer include their own padding. Instead, the system adds
    329 padding for each widget, based the characteristics of the current screen.
    330 This leads to a more uniform, consistent presentation of widgets in a grid.
    331 To assist applications that host app widgets, the platform provides
    332 the method
    333 {@link android.appwidget.AppWidgetHostView#getDefaultPaddingForWidget getDefaultPaddingForWidget()}.
    334 Applications can call this method to get the system-defined padding
    335 and account for it when computing the number of cells to allocate to the widget.</p>
    336 
    337 <h3 id="41">Android 4.1</h3>
    338 
    339 <p>Android 4.1 (API Level 16) adds an API that allows the widget provider
    340 to get more detailed information  about the environment in which its
    341 widget instances are being hosted. Specifically, the host hints to the
    342 widget provider about the size at which the widget is being displayed.
    343 It is the hosts responsibility to provide this size information.</p>
    344 
    345 <p>The host provides this information via
    346 {@link android.appwidget.AppWidgetHostView#updateAppWidgetSize updateAppWidgetSize()}.
    347 The size is specified as a minimum and maximum width/height in dps.
    348 The reason that a range is specified (as opposed to a fixed size)
    349 is because the width and height of a widget may change with orientation.
    350 You dont want the host to have to update all of its widgets on rotation,
    351 as this could cause serious system slowdown. These values should be
    352 updated once upon the widget being placed, any time the widget is resized,
    353 and any time the launcher inflates the widget for the first time in a
    354 given boot (as the values arent persisted across boot).</p>
    355 
    356 
    357 <h3 id="42">Android 4.2</h3>
    358 
    359 <p>Android 4.2 (API Level 17) adds the ability for the options bundle
    360 to be specified at bind time. This is the ideal way to specify app
    361 widget options, including size, as it gives the {@link
    362 android.appwidget.AppWidgetProvider} immediate access to the options
    363 data on the first update. This can be achieved by using the method {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int,android.content.ComponentName,android.os.Bundle) bindAppWidgetIdIfAllowed()}. For more discussion of this topic,
    364 see <a href="#host-binding">Binding app widgets</a>.</p>
    365 
    366 <p>Android 4.2 also introduces lockscreen widgets. When hosting widgets
    367 on the lockscreen, the host must specify this information within the app
    368 widget options bundle (the {@link
    369 android.appwidget.AppWidgetProvider} can use this information to style
    370 the widget appropriately). To designate a widget as a lockscreen widget, use {@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions updateAppWidgetOptions()}
    371 and include the field
    372 {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_HOST_CATEGORY}
    373 with the value {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}.
    374 This option defaults to
    375 {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN},
    376 so it is not explicitly required to set this for a home screen host.</p>
    377 
    378 <p>Make sure that your host adds only app widgets that are appropriate
    379 for your app&mdash;for example, if your host is a home screen, ensure
    380 that the
    381 {@link android.appwidget.AppWidgetProviderInfo#widgetCategory android:widgetCategory}
    382 attribute in the 
    383 {@link android.appwidget.AppWidgetProviderInfo} metadata includes
    384 the flag {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN}.
    385 Similarly, for the lockscreen, ensure that field includes the flag  {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}. For more
    386 discussion of this topic, see
    387 <a href="{@docRoot}guide/topics/appwidgets/index.html#lockscreen">
    388 Enabling App Widgets on the Lockscreen</a>.</p>
    389 
    390 
    391 
    392 
    393