| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 1 | page.title=App Widget Host |
| Joe Fernandez | 33baa5a | 2013-11-14 11:41:19 -0800 | [diff] [blame] | 2 | page.tags=AppWidgetHost,home screen,launcher |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 3 | @jd:body |
| 4 | |
| 5 | <div id="qv-wrapper"> |
| 6 | <div id="qv"> |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 7 | |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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}. |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 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 |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 37 | a host implicitly agrees to.</p> |
| 38 | |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 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 |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 41 | {@link android.appwidget.AppWidgetHost}, see the source code for the |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 42 | Android Home screen |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 43 | <a href="https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/Launcher.java"> |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 44 | Launcher</a>. |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 45 | |
| 46 | |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 47 | <p>Here is an overview of key classes and concepts involved in implementing a custom |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 48 | {@link android.appwidget.AppWidgetHost}:</p> |
| 49 | <ul> |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 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 |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 55 | across all uses of the host. The ID is typically a hard-coded value that you assign |
| 56 | in your application.</li> |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 57 | |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 58 | <li><strong>App Widget ID</strong>— |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 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 |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 65 | associated with the app widget ID. |
| 66 | </li> |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 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 |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 72 | widget is inflated by the host. </li> |
| 73 | <li><strong>Options Bundle</strong>— |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 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 |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 79 | and appearance based on how and where it is displayed. |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 80 | You use |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 81 | {@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions(android.os.Bundle) updateAppWidgetOptions()} |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 82 | and |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 83 | {@link android.appwidget.AppWidgetHostView#updateAppWidgetSize updateAppWidgetSize()} |
| 84 | |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 85 | to modify an app widget's |
| 86 | bundle. Both of these methods trigger a callback to the |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 | |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 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 |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 | ... |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 121 | int appWidgetId = |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 122 | Launcher.this.mAppWidgetHost.allocateAppWidgetId(); |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 123 | Intent pickIntent = |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 | |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 138 | <pre>public final class Launcher extends Activity |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 | } |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 155 | } |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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); |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 167 | AppWidgetProviderInfo appWidget = |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 186 | actual work of adding it to the workspace. The |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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, |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 204 | you use the |
| 205 | {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()} |
| 206 | method. |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 207 | If {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()} |
| 208 | returns {@code false}, your app must display a dialog prompting the |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 209 | user to grant permission |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 | |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 221 | <p>The host also has to check whether the user added |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 222 | an app widget that needs configuration. For more discussion of this topic, |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 223 | see |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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> |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 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 |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 239 | puts the responsibility on the |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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> |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 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()} |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 246 | method. It also introduces lockscreen widgets.</li> |
| 247 | </ul> |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 248 | <p>If you are targeting earlier devices, refer to the original |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 276 | (using {@link android.appwidget.AppWidgetProviderInfo#minWidth android:minWidth} and |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 host’s 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 host’s 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 don’t 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 aren’t 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} |
| Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 382 | attribute in the |
| kmccormick | 25072c7 | 2013-03-01 16:13:21 -0800 | [diff] [blame] | 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 | |