host.jd revision 33baa5ad7d8cdcc89ce4fbc3bc8cd537d5f5d639
1page.title=App Widget Host
2page.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
31to embed <a href="{@docRoot}guide/topics/appwidgets/index.html">app widgets</a> for quick
32access to content. If you're building a Home replacement or a similar app,
33you can also allow the user to embed app widgets by implementing an
34{@link android.appwidget.AppWidgetHost}.
35This is not something that most apps will ever need to do, but if you are 
36creating your own host, it's important to understand the contractual obligations 
37a 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
42Android Home screen 
43<a href="https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/Launcher.java">
44Launcher</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 
52with the AppWidget service for apps, like the home screen, that want to embed 
53app widgets in their UI. An {@link android.appwidget.AppWidgetHost} must have 
54an ID that is unique within the host's own package. This ID remains persistent 
55across all uses of the host. The ID is typically a hard-coded value that you assign
56in 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()}, 
61discussed in more detail in <a href="#binding">Binding app widgets</a>). 
62The unique ID is obtained by the host using {@link android.appwidget.AppWidgetHost#allocateAppWidgetId() allocateAppWidgetId()}. This ID is persistent across the lifetime of the widget, 
63that is, until it is deleted from the host. Any host-specific state (such as the 
64size and location of the widget) should be persisted by the hosting package and 
65associated 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 
70that the widget is wrapped in whenever it needs to be displayed. An app widget 
71is assigned to an {@link android.appwidget.AppWidgetHostView} every time the 
72widget is inflated by the host. </li>
73    <li><strong>Options Bundle</strong>&mdash;
74The {@link android.appwidget.AppWidgetHost} uses the options bundle to communicate 
75information to the {@link android.appwidget.AppWidgetProvider} about how the 
76widget is being displayed (for example, size range, and whether the widget is on 
77a lockscreen or the home screen). This information allows the 
78{@link android.appwidget.AppWidgetProvider} to tailor the widget's contents 
79and appearance based on how and where it is  displayed.
80You use 
81{@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions(android.os.Bundle) updateAppWidgetOptions()}
82and 
83{@link android.appwidget.AppWidgetHostView#updateAppWidgetSize updateAppWidgetSize()}
84
85to modify an app widget's 
86bundle. 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
94a particular app widget ID to a specific host and to a specific
95{@link android.appwidget.AppWidgetProvider}. There are different
96ways of achieving this, depending on what version of Android your
97app 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 
102via a system activity that allows users to select a widget. This implicitly 
103does a permission check&mdash;that is, by adding the app widget, the user is 
104implicitly granting permission to your app to add app widgets to the host. 
105Here is an example that illustrates 
106this 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()} 
109with the request code {@code REQUEST_PICK_APPWIDGET} in response to a 
110user action:</p>
111
112<pre>
113private static final int REQUEST_CREATE_APPWIDGET = 5;
114private static final int REQUEST_PICK_APPWIDGET = 9;
115...
116public 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
135app widget to your activity. In the following example, the activity responds
136by 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
161needs 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,
182see <a href="{@docRoot}guide/topics/appwidgets/index.html#Configuring">Creating an
183App Widget Configuration Activity</a>.</p>
184
185<p>Once the app widget is ready, the next step is to do the
186actual 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()}
188to 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.
193These APIs also make it possible for a host to provide a custom UI for
194binding. 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
202explicitly grant permission to your app to allow it to add app widgets
203to the host. To test whether your app has permission to add the widget,
204you use the 
205{@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()} 
206method. 
207If {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()}
208returns {@code false}, your app must display a dialog prompting the
209user to grant permission 
210("allow" or "always allow," to cover all future app widget additions).
211This snippet gives an example of how to display the dialog:</p>
212
213<pre>Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
214intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
215intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
216// This is the options bundle discussed above
217intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
218startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
219</pre>
220
221<p>The host also has to check whether the user added 
222an app widget that needs configuration. For more discussion of this topic,
223see 
224<a href="{@docRoot}guide/topics/appwidgets/index.html#Configuring">Creating
225an 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  
233you're targeting. Many of the features described in this section were introduced 
234in 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
239puts the responsibility on the 
240host to manage padding.</li>
241<li>Android 4.1 (API Level 16) adds an API that allows the widget provider
242to get more detailed information about the environment in which its
243widget 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()} 
246method. 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
254for widgets using the <a href="{@docRoot}guide/topics/appwidgets/index.html#MetaData">
255AppWidgetProviderInfo metadata</a>.
256These configuration options, discussed in more detail below, can be
257retrieved by the host from the {@link android.appwidget.AppWidgetProviderInfo}
258object associated with a widget provider.</p>
259
260<p>Regardless of the version of Android you are targeting, all hosts
261have the following responsibilities:</p>
262
263<ul>
264<li>When adding a widget, you must allocate the widget ID as described above.
265You must also make sure that when a widget is removed from the host, you call {@link android.appwidget.AppWidgetHost#deleteAppWidgetId deleteAppWidgetId()}
266to deallocate the widget ID.</li>
267
268<li>When adding a widget, be sure to launch its configuration activity
269if it exists, as described in
270<a href="{@docRoot}guide/topics/appwidgets/index.html#UpdatingFromTheConfiguration">
271Updating the App Widget
272from the Configuration Activity</a>. This is a necessary step for many app widgets before
273they 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}).
278Make sure that the widget is laid out with at least this many dps.
279For example, many hosts align icons and widgets in a grid. In this scenario,
280by default the host should add the app widget using the minimum number of
281cells 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
286versions introduce features that place new responsibilities on the
287host. 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()}.
292This view ID should point to an instance of an
293{@link android.widget.Advanceable}, such as {@link android.widget.StackView}
294or {@link android.widget.AdapterViewFlipper}. This indicates that the host
295should call {@link android.widget.Advanceable#advance advance()} on this
296view at an interval deemed appropriate by the host (taking into account whether
297it makes sense to advance the widget&mdash;for example, the host probably
298wouldn't want to advance a widget if it were on another page, or
299if 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.
304A widget can specify that it is resizable using the
305{@link android.appwidget.AppWidgetProviderInfo#resizeMode android:resizeMode}
306attribute in the {@link android.appwidget.AppWidgetProviderInfo}
307metadata, and indicate whether it supports horizontal and/or
308vertical resizing. Introduced in Android 4.0 (API Level 14), the widget can also specify a
309{@link android.appwidget.AppWidgetProviderInfo#minResizeWidth android:minResizeWidth}
310and/or {@link android.appwidget.AppWidgetProviderInfo#minResizeHeight android:minResizeHeight}.</p>
311
312<p>It is the host’s responsibility to make it possible for the
313widget to be resized horizontally and/or vertically, as specified
314by the widget. A widget that specifies that it is resizable can be
315resized arbitrarily large, but should not be resized smaller than
316the values specified by {@link
317android.appwidget.AppWidgetProviderInfo#minResizeWidth android:minResizeWidth}
318and {@link
319android.appwidget.AppWidgetProviderInfo#minResizeHeight android:minResizeHeight}.
320For 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
327puts the responsibility on the host to manage padding. As of 4.0, app
328widgets no longer include their own padding. Instead, the system adds
329padding for each widget, based the characteristics of the current screen.
330This leads to a more uniform, consistent presentation of widgets in a grid.
331To assist applications that host app widgets, the platform provides
332the method
333{@link android.appwidget.AppWidgetHostView#getDefaultPaddingForWidget getDefaultPaddingForWidget()}.
334Applications can call this method to get the system-defined padding
335and 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
340to get more detailed information  about the environment in which its
341widget instances are being hosted. Specifically, the host hints to the
342widget provider about the size at which the widget is being displayed.
343It 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()}.
347The size is specified as a minimum and maximum width/height in dps.
348The reason that a range is specified (as opposed to a fixed size)
349is because the width and height of a widget may change with orientation.
350You don’t want the host to have to update all of its widgets on rotation,
351as this could cause serious system slowdown. These values should be
352updated once upon the widget being placed, any time the widget is resized,
353and any time the launcher inflates the widget for the first time in a
354given 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
360to be specified at bind time. This is the ideal way to specify app
361widget options, including size, as it gives the {@link
362android.appwidget.AppWidgetProvider} immediate access to the options
363data 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,
364see <a href="#host-binding">Binding app widgets</a>.</p>
365
366<p>Android 4.2 also introduces lockscreen widgets. When hosting widgets
367on the lockscreen, the host must specify this information within the app
368widget options bundle (the {@link
369android.appwidget.AppWidgetProvider} can use this information to style
370the widget appropriately). To designate a widget as a lockscreen widget, use {@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions updateAppWidgetOptions()}
371and include the field
372{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_HOST_CATEGORY}
373with the value {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}.
374This option defaults to
375{@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN},
376so 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
379for your app&mdash;for example, if your host is a home screen, ensure
380that the
381{@link android.appwidget.AppWidgetProviderInfo#widgetCategory android:widgetCategory}
382attribute in the 
383{@link android.appwidget.AppWidgetProviderInfo} metadata includes
384the flag {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN}.
385Similarly, for the lockscreen, ensure that field includes the flag  {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}. For more
386discussion of this topic, see
387<a href="{@docRoot}guide/topics/appwidgets/index.html#lockscreen">
388Enabling App Widgets on the Lockscreen</a>.</p>
389
390
391
392
393