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>— 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>— 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>— 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>— 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—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 @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><uses-permission android:name="android.permission.BIND_APPWIDGET" /> 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—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—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