• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.appwidget;
18 
19 import android.annotation.Nullable;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.ParceledListSlice;
24 import android.os.Bundle;
25 import android.os.IBinder;
26 import android.os.Process;
27 import android.os.RemoteException;
28 import android.os.UserHandle;
29 import android.util.DisplayMetrics;
30 import android.util.TypedValue;
31 import android.widget.RemoteViews;
32 
33 import com.android.internal.appwidget.IAppWidgetService;
34 
35 import java.util.Collections;
36 import java.util.List;
37 
38 /**
39  * Updates AppWidget state; gets information about installed AppWidget providers and other
40  * AppWidget related state.
41  *
42  * <div class="special reference">
43  * <h3>Developer Guides</h3>
44  * <p>For more information about creating app widgets, read the
45  * <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> developer guide.</p>
46  * </div>
47  */
48 public class AppWidgetManager {
49 
50     /**
51      * Activity action to launch from your {@link AppWidgetHost} activity when you want to
52      * pick an AppWidget to display.  The AppWidget picker activity will be launched.
53      * <p>
54      * You must supply the following extras:
55      * <table>
56      *   <tr>
57      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
58      *     <td>A newly allocated appWidgetId, which will be bound to the AppWidget provider
59      *         once the user has selected one.</td>
60      *  </tr>
61      * </table>
62      *
63      * <p>
64      * The system will respond with an onActivityResult call with the following extras in
65      * the intent:
66      * <table>
67      *   <tr>
68      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
69      *     <td>The appWidgetId that you supplied in the original intent.</td>
70      *  </tr>
71      * </table>
72      * <p>
73      * When you receive the result from the AppWidget pick activity, if the resultCode is
74      * {@link android.app.Activity#RESULT_OK}, an AppWidget has been selected.  You should then
75      * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its
76      * configuration activity.  If {@link android.app.Activity#RESULT_CANCELED} is returned, you
77      * should delete the appWidgetId.
78      *
79      * @see #ACTION_APPWIDGET_CONFIGURE
80      */
81     public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
82 
83     /**
84      * Similar to ACTION_APPWIDGET_PICK, but used from keyguard
85      * @hide
86      */
87     public static final String
88             ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK";
89 
90     /**
91      * Activity action to launch from your {@link AppWidgetHost} activity when you want to bind
92      * an AppWidget to display and bindAppWidgetIdIfAllowed returns false.
93      * <p>
94      * You must supply the following extras:
95      * <table>
96      *   <tr>
97      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
98      *     <td>A newly allocated appWidgetId, which will be bound to the AppWidget provider
99      *         you provide.</td>
100      *  </tr>
101      *  <tr>
102      *     <td>{@link #EXTRA_APPWIDGET_PROVIDER}</td>
103      *     <td>The BroadcastReceiver that will be the AppWidget provider for this AppWidget.
104      *     </td>
105      *  </tr>
106      *  <tr>
107      *     <td>{@link #EXTRA_APPWIDGET_PROVIDER_PROFILE}</td>
108      *     <td>An optional handle to a user profile under which runs the provider
109      *     for this AppWidget.
110      *     </td>
111      *  </tr>
112      * </table>
113      *
114      * <p>
115      * The system will respond with an onActivityResult call with the following extras in
116      * the intent:
117      * <table>
118      *   <tr>
119      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
120      *     <td>The appWidgetId that you supplied in the original intent.</td>
121      *  </tr>
122      * </table>
123      * <p>
124      * When you receive the result from the AppWidget bind activity, if the resultCode is
125      * {@link android.app.Activity#RESULT_OK}, the AppWidget has been bound.  You should then
126      * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its
127      * configuration activity.  If {@link android.app.Activity#RESULT_CANCELED} is returned, you
128      * should delete the appWidgetId.
129      *
130      * @see #ACTION_APPWIDGET_CONFIGURE
131      *
132      */
133     public static final String ACTION_APPWIDGET_BIND = "android.appwidget.action.APPWIDGET_BIND";
134 
135     /**
136      * Sent when it is time to configure your AppWidget while it is being added to a host.
137      * This action is not sent as a broadcast to the AppWidget provider, but as a startActivity
138      * to the activity specified in the {@link AppWidgetProviderInfo AppWidgetProviderInfo
139      * meta-data}.
140      *
141      * <p>
142      * The intent will contain the following extras:
143      * <table>
144      *   <tr>
145      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
146      *     <td>The appWidgetId to configure.</td>
147      *  </tr>
148      * </table>
149      *
150      * <p>If you return {@link android.app.Activity#RESULT_OK} using
151      * {@link android.app.Activity#setResult Activity.setResult()}, the AppWidget will be added,
152      * and you will receive an {@link #ACTION_APPWIDGET_UPDATE} broadcast for this AppWidget.
153      * If you return {@link android.app.Activity#RESULT_CANCELED}, the host will cancel the add
154      * and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED}
155      * broadcast.
156      */
157     public static final String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE";
158 
159     /**
160      * An intent extra that contains one appWidgetId.
161      * <p>
162      * The value will be an int that can be retrieved like this:
163      * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java getExtra_EXTRA_APPWIDGET_ID}
164      */
165     public static final String EXTRA_APPWIDGET_ID = "appWidgetId";
166 
167     /**
168      * A bundle extra that contains the lower bound on the current width, in dips, of a widget instance.
169      */
170     public static final String OPTION_APPWIDGET_MIN_WIDTH = "appWidgetMinWidth";
171 
172     /**
173      * A bundle extra that contains the lower bound on the current height, in dips, of a widget instance.
174      */
175     public static final String OPTION_APPWIDGET_MIN_HEIGHT = "appWidgetMinHeight";
176 
177     /**
178      * A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
179      */
180     public static final String OPTION_APPWIDGET_MAX_WIDTH = "appWidgetMaxWidth";
181 
182     /**
183      * A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
184      */
185     public static final String OPTION_APPWIDGET_MAX_HEIGHT = "appWidgetMaxHeight";
186 
187     /**
188      * A bundle extra that hints to the AppWidgetProvider the category of host that owns this
189      * this widget. Can have the value {@link
190      * AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
191      * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD} or {@link
192      * AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}.
193      */
194     public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
195 
196     /**
197      * An intent extra which points to a bundle of extra information for a particular widget id.
198      * In particular this bundle can contain {@link #OPTION_APPWIDGET_MIN_WIDTH},
199      * {@link #OPTION_APPWIDGET_MIN_HEIGHT}, {@link #OPTION_APPWIDGET_MAX_WIDTH},
200      * {@link #OPTION_APPWIDGET_MAX_HEIGHT}.
201      */
202     public static final String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions";
203 
204     /**
205      * An intent extra that contains multiple appWidgetIds.
206      * <p>
207      * The value will be an int array that can be retrieved like this:
208      * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java getExtra_EXTRA_APPWIDGET_IDS}
209      */
210     public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds";
211 
212     /**
213      * An intent extra that contains the component name of a AppWidget provider.
214      * <p>
215      * The value will be an {@link android.content.ComponentName}.
216      */
217     public static final String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider";
218 
219     /**
220      * An intent extra that contains the user handle of the profile under
221      * which an AppWidget provider is registered.
222      * <p>
223      * The value will be a {@link android.os.UserHandle}.
224      */
225     public static final String EXTRA_APPWIDGET_PROVIDER_PROFILE = "appWidgetProviderProfile";
226 
227     /**
228      * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
229      * {@link AppWidgetProviderInfo} objects to mix in to the list of AppWidgets that are
230      * installed.  (This is how the launcher shows the search widget).
231      */
232     public static final String EXTRA_CUSTOM_INFO = "customInfo";
233 
234     /**
235      * An intent extra attached to the {@link #ACTION_APPWIDGET_HOST_RESTORED} broadcast,
236      * indicating the integer ID of the host whose widgets have just been restored.
237      */
238     public static final String EXTRA_HOST_ID = "hostId";
239 
240     /**
241      * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
242      * {@link android.os.Bundle} objects to mix in to the list of AppWidgets that are
243      * installed.  It will be added to the extras object on the {@link android.content.Intent}
244      * that is returned from the picker activity.
245      *
246      * {@more}
247      */
248     public static final String EXTRA_CUSTOM_EXTRAS = "customExtras";
249 
250     /**
251      * An intent extra to pass to the AppWidget picker which allows the picker to filter
252      * the list based on the {@link AppWidgetProviderInfo#widgetCategory}.
253      *
254      * @hide
255      */
256     public static final String EXTRA_CATEGORY_FILTER = "categoryFilter";
257 
258     /**
259      * An intent extra to pass to the AppWidget picker to specify whether or not to sort
260      * the list of caller-specified extra AppWidgets along with the rest of the AppWidgets
261      * @hide
262      */
263     public static final String EXTRA_CUSTOM_SORT = "customSort";
264 
265     /**
266      * A sentinel value that the AppWidget manager will never return as a appWidgetId.
267      */
268     public static final int INVALID_APPWIDGET_ID = 0;
269 
270     /**
271      * Sent when it is time to update your AppWidget.
272      *
273      * <p>This may be sent in response to a new instance for this AppWidget provider having
274      * been instantiated, the requested {@link AppWidgetProviderInfo#updatePeriodMillis update interval}
275      * having lapsed, or the system booting.
276      *
277      * <p>
278      * The intent will contain the following extras:
279      * <table>
280      *   <tr>
281      *     <td>{@link #EXTRA_APPWIDGET_IDS}</td>
282      *     <td>The appWidgetIds to update.  This may be all of the AppWidgets created for this
283      *     provider, or just a subset.  The system tries to send updates for as few AppWidget
284      *     instances as possible.</td>
285      *  </tr>
286      * </table>
287      *
288      * @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
289      */
290     public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";
291 
292     /**
293      * Sent when the custom extras for an AppWidget change.
294      *
295      * <p class="note">This is a protected intent that can only be sent
296      * by the system.
297      *
298      * @see AppWidgetProvider#onAppWidgetOptionsChanged
299      *      AppWidgetProvider.onAppWidgetOptionsChanged(Context context,
300      *      AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras)
301      */
302     public static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS";
303 
304     /**
305      * Sent when an instance of an AppWidget is deleted from its host.
306      *
307      * <p class="note">This is a protected intent that can only be sent
308      * by the system.
309      *
310      * @see AppWidgetProvider#onDeleted AppWidgetProvider.onDeleted(Context context, int[] appWidgetIds)
311      */
312     public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED";
313 
314     /**
315      * Sent when the last AppWidget of this provider is removed from the last host.
316      *
317      * <p class="note">This is a protected intent that can only be sent
318      * by the system.
319      *
320      * @see AppWidgetProvider#onEnabled AppWidgetProvider.onDisabled(Context context)
321      */
322     public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED";
323 
324     /**
325      * Sent when an instance of an AppWidget is added to a host for the first time.
326      * This broadcast is sent at boot time if there is a AppWidgetHost installed with
327      * an instance for this provider.
328      *
329      * <p class="note">This is a protected intent that can only be sent
330      * by the system.
331      *
332      * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
333      */
334     public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED";
335 
336     /**
337      * Sent to an {@link AppWidgetProvider} after AppWidget state related to that provider has
338      * been restored from backup. The intent contains information about how to translate AppWidget
339      * ids from the restored data to their new equivalents.
340      *
341      * <p>The intent will contain the following extras:
342      *
343      * <table>
344      *   <tr>
345      *     <td>{@link #EXTRA_APPWIDGET_OLD_IDS}</td>
346      *     <td>The set of appWidgetIds represented in a restored backup that have been successfully
347      *     incorporated into the current environment.  This may be all of the AppWidgets known
348      *     to this application, or just a subset.  Each entry in this array of appWidgetIds has
349      *     a corresponding entry in the {@link #EXTRA_APPWIDGET_IDS} extra.</td>
350      *  </tr>
351      *   <tr>
352      *     <td>{@link #EXTRA_APPWIDGET_IDS}</td>
353      *     <td>The set of appWidgetIds now valid for this application.  The app should look at
354      *     its restored widget configuration and translate each appWidgetId in the
355      *     {@link #EXTRA_APPWIDGET_OLD_IDS} array to its new value found at the corresponding
356      *     index within this array.</td>
357      *  </tr>
358      * </table>
359      *
360      * <p class="note">This is a protected intent that can only be sent
361      * by the system.
362      *
363      * @see #ACTION_APPWIDGET_HOST_RESTORED
364      */
365     public static final String ACTION_APPWIDGET_RESTORED
366             = "android.appwidget.action.APPWIDGET_RESTORED";
367 
368     /**
369      * Sent to widget hosts after AppWidget state related to the host has been restored from
370      * backup. The intent contains information about how to translate AppWidget ids from the
371      * restored data to their new equivalents.  If an application maintains multiple separate
372      * widget host instances, it will receive this broadcast separately for each one.
373      *
374      * <p>The intent will contain the following extras:
375      *
376      * <table>
377      *   <tr>
378      *     <td>{@link #EXTRA_APPWIDGET_OLD_IDS}</td>
379      *     <td>The set of appWidgetIds represented in a restored backup that have been successfully
380      *     incorporated into the current environment.  This may be all of the AppWidgets known
381      *     to this application, or just a subset.  Each entry in this array of appWidgetIds has
382      *     a corresponding entry in the {@link #EXTRA_APPWIDGET_IDS} extra.</td>
383      *  </tr>
384      *   <tr>
385      *     <td>{@link #EXTRA_APPWIDGET_IDS}</td>
386      *     <td>The set of appWidgetIds now valid for this application.  The app should look at
387      *     its restored widget configuration and translate each appWidgetId in the
388      *     {@link #EXTRA_APPWIDGET_OLD_IDS} array to its new value found at the corresponding
389      *     index within this array.</td>
390      *  </tr>
391      *  <tr>
392      *     <td>{@link #EXTRA_HOST_ID}</td>
393      *     <td>The integer ID of the widget host instance whose state has just been restored.</td>
394      *  </tr>
395      * </table>
396      *
397      * <p class="note">This is a protected intent that can only be sent
398      * by the system.
399      *
400      * @see #ACTION_APPWIDGET_RESTORED
401      */
402     public static final String ACTION_APPWIDGET_HOST_RESTORED
403             = "android.appwidget.action.APPWIDGET_HOST_RESTORED";
404 
405     /**
406      * An intent extra that contains multiple appWidgetIds.  These are id values as
407      * they were provided to the application during a recent restore from backup.  It is
408      * attached to the {@link #ACTION_APPWIDGET_RESTORED} broadcast intent.
409      *
410      * <p>
411      * The value will be an int array that can be retrieved like this:
412      * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java getExtra_EXTRA_APPWIDGET_IDS}
413      */
414     public static final String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds";
415 
416     /**
417      * Field for the manifest meta-data tag.
418      *
419      * @see AppWidgetProviderInfo
420      */
421     public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";
422 
423     private final String mPackageName;
424 
425     private final IAppWidgetService mService;
426 
427     private final DisplayMetrics mDisplayMetrics;
428 
429     /**
430      * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context
431      * Context} object.
432      */
getInstance(Context context)433     public static AppWidgetManager getInstance(Context context) {
434         return (AppWidgetManager) context.getSystemService(Context.APPWIDGET_SERVICE);
435     }
436 
437     /**
438      * Creates a new instance.
439      *
440      * @param context The current context in which to operate.
441      * @param service The backing system service.
442      * @hide
443      */
AppWidgetManager(Context context, IAppWidgetService service)444     public AppWidgetManager(Context context, IAppWidgetService service) {
445         mPackageName = context.getOpPackageName();
446         mService = service;
447         mDisplayMetrics = context.getResources().getDisplayMetrics();
448     }
449 
450     /**
451      * Set the RemoteViews to use for the specified appWidgetIds.
452      * <p>
453      * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should
454      * contain a complete representation of the widget. For performing partial widget updates, see
455      * {@link #partiallyUpdateAppWidget(int[], RemoteViews)}.
456      *
457      * <p>
458      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
459      * and outside of the handler.
460      * This method will only work when called from the uid that owns the AppWidget provider.
461      *
462      * <p>
463      * The total Bitmap memory used by the RemoteViews object cannot exceed that required to
464      * fill the screen 1.5 times, ie. (screen width x screen height x 4 x 1.5) bytes.
465      *
466      * @param appWidgetIds The AppWidget instances for which to set the RemoteViews.
467      * @param views The RemoteViews object to show.
468      */
updateAppWidget(int[] appWidgetIds, RemoteViews views)469     public void updateAppWidget(int[] appWidgetIds, RemoteViews views) {
470         if (mService == null) {
471             return;
472         }
473         try {
474             mService.updateAppWidgetIds(mPackageName, appWidgetIds, views);
475         }
476         catch (RemoteException e) {
477             throw new RuntimeException("system server dead?", e);
478         }
479     }
480 
481     /**
482      * Update the extras for a given widget instance.
483      * <p>
484      * The extras can be used to embed additional information about this widget to be accessed
485      * by the associated widget's AppWidgetProvider.
486      *
487      * @see #getAppWidgetOptions(int)
488      *
489      * @param appWidgetId The AppWidget instances for which to set the RemoteViews.
490      * @param options The options to associate with this widget
491      */
updateAppWidgetOptions(int appWidgetId, Bundle options)492     public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
493         if (mService == null) {
494             return;
495         }
496         try {
497             mService.updateAppWidgetOptions(mPackageName, appWidgetId, options);
498         }
499         catch (RemoteException e) {
500             throw new RuntimeException("system server dead?", e);
501         }
502     }
503 
504     /**
505      * Get the extras associated with a given widget instance.
506      * <p>
507      * The extras can be used to embed additional information about this widget to be accessed
508      * by the associated widget's AppWidgetProvider.
509      *
510      * @see #updateAppWidgetOptions(int, Bundle)
511      *
512      * @param appWidgetId The AppWidget instances for which to set the RemoteViews.
513      * @return The options associated with the given widget instance.
514      */
getAppWidgetOptions(int appWidgetId)515     public Bundle getAppWidgetOptions(int appWidgetId) {
516         if (mService == null) {
517             return Bundle.EMPTY;
518         }
519         try {
520             return mService.getAppWidgetOptions(mPackageName, appWidgetId);
521         }
522         catch (RemoteException e) {
523             throw new RuntimeException("system server dead?", e);
524         }
525     }
526 
527     /**
528      * Set the RemoteViews to use for the specified appWidgetId.
529      * <p>
530      * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should
531      * contain a complete representation of the widget. For performing partial widget updates, see
532      * {@link #partiallyUpdateAppWidget(int, RemoteViews)}.
533      *
534      * <p>
535      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
536      * and outside of the handler.
537      * This method will only work when called from the uid that owns the AppWidget provider.
538      *
539      * <p>
540      * The total Bitmap memory used by the RemoteViews object cannot exceed that required to
541      * fill the screen 1.5 times, ie. (screen width x screen height x 4 x 1.5) bytes.
542      *
543      * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
544      * @param views         The RemoteViews object to show.
545      */
updateAppWidget(int appWidgetId, RemoteViews views)546     public void updateAppWidget(int appWidgetId, RemoteViews views) {
547         if (mService == null) {
548             return;
549         }
550         updateAppWidget(new int[] { appWidgetId }, views);
551     }
552 
553     /**
554      * Perform an incremental update or command on the widget(s) specified by appWidgetIds.
555      * <p>
556      * This update  differs from {@link #updateAppWidget(int[], RemoteViews)} in that the
557      * RemoteViews object which is passed is understood to be an incomplete representation of the
558      * widget, and hence does not replace the cached representation of the widget. As of API
559      * level 17, the new properties set within the views objects will be appended to the cached
560      * representation of the widget, and hence will persist.
561      *
562      * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
563      * {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
564      *
565      * <p>
566      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
567      * and outside of the handler.
568      * This method will only work when called from the uid that owns the AppWidget provider.
569      *
570      * <p>
571      * This method will be ignored if a widget has not received a full update via
572      * {@link #updateAppWidget(int[], RemoteViews)}.
573      *
574      * @param appWidgetIds     The AppWidget instances for which to set the RemoteViews.
575      * @param views            The RemoteViews object containing the incremental update / command.
576      */
partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views)577     public void partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views) {
578         if (mService == null) {
579             return;
580         }
581         try {
582             mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views);
583         } catch (RemoteException e) {
584             throw new RuntimeException("system server dead?", e);
585         }
586     }
587 
588     /**
589      * Perform an incremental update or command on the widget specified by appWidgetId.
590      * <p>
591      * This update  differs from {@link #updateAppWidget(int, RemoteViews)} in that the RemoteViews
592      * object which is passed is understood to be an incomplete representation of the widget, and
593      * hence is not cached by the AppWidgetService. Note that because these updates are not cached,
594      * any state that they modify that is not restored by restoreInstanceState will not persist in
595      * the case that the widgets are restored using the cached version in AppWidgetService.
596      *
597      * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
598      * {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
599      *
600      * <p>
601      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
602      * and outside of the handler.
603      * This method will only work when called from the uid that owns the AppWidget provider.
604      *
605      * <p>
606      * This method will be ignored if a widget has not received a full update via
607      * {@link #updateAppWidget(int[], RemoteViews)}.
608      *
609      * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
610      * @param views            The RemoteViews object containing the incremental update / command.
611      */
partiallyUpdateAppWidget(int appWidgetId, RemoteViews views)612     public void partiallyUpdateAppWidget(int appWidgetId, RemoteViews views) {
613         if (mService == null) {
614             return;
615         }
616         partiallyUpdateAppWidget(new int[] { appWidgetId }, views);
617     }
618 
619     /**
620      * Set the RemoteViews to use for all AppWidget instances for the supplied AppWidget provider.
621      *
622      * <p>
623      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
624      * and outside of the handler.
625      * This method will only work when called from the uid that owns the AppWidget provider.
626      *
627      * @param provider      The {@link ComponentName} for the {@link
628      * android.content.BroadcastReceiver BroadcastReceiver} provider
629      *                      for your AppWidget.
630      * @param views         The RemoteViews object to show.
631      */
updateAppWidget(ComponentName provider, RemoteViews views)632     public void updateAppWidget(ComponentName provider, RemoteViews views) {
633         if (mService == null) {
634             return;
635         }
636         try {
637             mService.updateAppWidgetProvider(provider, views);
638         }
639         catch (RemoteException e) {
640             throw new RuntimeException("system server dead?", e);
641         }
642     }
643 
644     /**
645      * Notifies the specified collection view in all the specified AppWidget instances
646      * to invalidate their data.
647      *
648      * @param appWidgetIds  The AppWidget instances to notify of view data changes.
649      * @param viewId        The collection view id.
650      */
notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId)651     public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
652         if (mService == null) {
653             return;
654         }
655         try {
656             mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId);
657         }
658         catch (RemoteException e) {
659             throw new RuntimeException("system server dead?", e);
660         }
661     }
662 
663     /**
664      * Notifies the specified collection view in the specified AppWidget instance
665      * to invalidate its data.
666      *
667      * @param appWidgetId  The AppWidget instance to notify of view data changes.
668      * @param viewId       The collection view id.
669      */
notifyAppWidgetViewDataChanged(int appWidgetId, int viewId)670     public void notifyAppWidgetViewDataChanged(int appWidgetId, int viewId) {
671         if (mService == null) {
672             return;
673         }
674         notifyAppWidgetViewDataChanged(new int[] { appWidgetId }, viewId);
675     }
676 
677     /**
678      * Gets the AppWidget providers for the given user profile. User profile can only
679      * be the current user or a profile of the current user. For example, the current
680      * user may have a corporate profile. In this case the parent user profile has a
681      * child profile, the corporate one.
682      *
683      * @param profile The profile for which to get providers. Passing null is equivaled
684      *         to passing only the current user handle.
685      * @return The intalled providers.
686      *
687      * @see android.os.Process#myUserHandle()
688      * @see android.os.UserManager#getUserProfiles()
689      */
getInstalledProvidersForProfile(@ullable UserHandle profile)690     public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(@Nullable UserHandle profile) {
691         if (mService == null) {
692             return Collections.emptyList();
693         }
694         return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
695                 profile);
696     }
697 
698     /**
699      * Return a list of the AppWidget providers that are currently installed.
700      */
getInstalledProviders()701     public List<AppWidgetProviderInfo> getInstalledProviders() {
702         if (mService == null) {
703             return Collections.emptyList();
704         }
705         return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
706                 null);
707     }
708 
709     /**
710      * Gets the AppWidget providers for the current user.
711      *
712      * @param categoryFilter Will only return providers which register as any of the specified
713      *        specified categories. See {@link AppWidgetProviderInfo#widgetCategory}.
714      * @return The intalled providers.
715      *
716      * @see android.os.Process#myUserHandle()
717      * @see android.os.UserManager#getUserProfiles()
718      *
719      * @hide
720      */
getInstalledProviders(int categoryFilter)721     public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
722         if (mService == null) {
723             return Collections.emptyList();
724         }
725         return getInstalledProvidersForProfile(categoryFilter, null);
726     }
727 
728     /**
729      * Gets the AppWidget providers for the given user profile. User profile can only
730      * be the current user or a profile of the current user. For example, the current
731      * user may have a corporate profile. In this case the parent user profile has a
732      * child profile, the corporate one.
733      *
734      * @param categoryFilter Will only return providers which register as any of the specified
735      *        specified categories. See {@link AppWidgetProviderInfo#widgetCategory}.
736      * @param profile A profile of the current user which to be queried. The user
737      *        is itself also a profile. If null, the providers only for the current user
738      *        are returned.
739      * @return The intalled providers.
740      *
741      * @see android.os.Process#myUserHandle()
742      * @see android.os.UserManager#getUserProfiles()
743      *
744      * @hide
745      */
getInstalledProvidersForProfile(int categoryFilter, UserHandle profile)746     public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
747             UserHandle profile) {
748         if (mService == null) {
749             return Collections.emptyList();
750         }
751 
752         if (profile == null) {
753             profile = Process.myUserHandle();
754         }
755 
756         try {
757             ParceledListSlice<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
758                     categoryFilter, profile.getIdentifier());
759             if (providers == null) {
760                 return Collections.emptyList();
761             }
762             for (AppWidgetProviderInfo info : providers.getList()) {
763                 // Converting complex to dp.
764                 convertSizesToPixels(info);
765             }
766             return providers.getList();
767         }
768         catch (RemoteException e) {
769             throw new RuntimeException("system server dead?", e);
770         }
771     }
772 
773     /**
774      * Get the available info about the AppWidget.
775      *
776      * @return A appWidgetId.  If the appWidgetId has not been bound to a provider yet, or
777      * you don't have access to that appWidgetId, null is returned.
778      */
getAppWidgetInfo(int appWidgetId)779     public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
780         if (mService == null) {
781             return null;
782         }
783         try {
784             AppWidgetProviderInfo info = mService.getAppWidgetInfo(mPackageName, appWidgetId);
785             if (info != null) {
786                 // Converting complex to dp.
787                 convertSizesToPixels(info);
788             }
789             return info;
790         }
791         catch (RemoteException e) {
792             throw new RuntimeException("system server dead?", e);
793         }
794     }
795 
796     /**
797      * Set the component for a given appWidgetId.
798      *
799      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
800      *         widgets always for your component. This method is used by the AppWidget picker and
801      *         should not be used by other apps.
802      *
803      * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
804      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
805      *                      provider for this AppWidget.
806      * @hide
807      */
bindAppWidgetId(int appWidgetId, ComponentName provider)808     public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
809         if (mService == null) {
810             return;
811         }
812         bindAppWidgetId(appWidgetId, provider, null);
813     }
814 
815     /**
816      * Set the component for a given appWidgetId.
817      *
818      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
819      *         widgets always for your component. This method is used by the AppWidget picker and
820      *         should not be used by other apps.
821      *
822      * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
823      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
824      *                      provider for this AppWidget.
825      * @param options       Bundle containing options for the AppWidget. See also
826      *                      {@link #updateAppWidgetOptions(int, Bundle)}
827      *
828      * @hide
829      */
bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options)830     public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
831         if (mService == null) {
832             return;
833         }
834         bindAppWidgetIdIfAllowed(appWidgetId, Process.myUserHandle(), provider, options);
835     }
836 
837     /**
838      * Set the component for a given appWidgetId.
839      *
840      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
841      *         widgets always for your component. Should be used by apps that host widgets; if this
842      *         method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to
843      *         bind
844      *
845      * @param appWidgetId   The AppWidget id under which to bind the provider.
846      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
847      *                      provider for this AppWidget.
848      * @return true if this component has permission to bind the AppWidget
849      */
bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider)850     public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider) {
851         if (mService == null) {
852             return false;
853         }
854         return bindAppWidgetIdIfAllowed(appWidgetId, UserHandle.myUserId(), provider, null);
855     }
856 
857     /**
858      * Set the component for a given appWidgetId.
859      *
860      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
861      *         widgets always for your component. Should be used by apps that host widgets; if this
862      *         method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to
863      *         bind
864      *
865      * @param appWidgetId The AppWidget id under which to bind the provider.
866      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
867      *                      provider for this AppWidget.
868      * @param options       Bundle containing options for the AppWidget. See also
869      *                      {@link #updateAppWidgetOptions(int, Bundle)}
870      *
871      * @return true if this component has permission to bind the AppWidget
872      */
bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider, Bundle options)873     public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider,
874             Bundle options) {
875         if (mService == null) {
876             return false;
877         }
878         return bindAppWidgetIdIfAllowed(appWidgetId, UserHandle.myUserId(), provider, options);
879     }
880 
881     /**
882      * Set the provider for a given appWidgetId if the caller has a permission.
883      * <p>
884      * <strong>Note:</strong> You need the {@link android.Manifest.permission#BIND_APPWIDGET}
885      * permission or the user must have enabled binding widgets always for your component.
886      * Should be used by apps that host widgets. If this method returns false, call {@link
887      * #ACTION_APPWIDGET_BIND} to request permission to bind.
888      * </p>
889      *
890      * @param appWidgetId The AppWidget id under which to bind the provider.
891      * @param user The user id in which the provider resides.
892      * @param provider The component name of the provider.
893      * @param options An optional Bundle containing options for the AppWidget.
894      *
895      * @return true if this component has permission to bind the AppWidget
896      */
bindAppWidgetIdIfAllowed(int appWidgetId, UserHandle user, ComponentName provider, Bundle options)897     public boolean bindAppWidgetIdIfAllowed(int appWidgetId, UserHandle user,
898             ComponentName provider, Bundle options) {
899         if (mService == null) {
900             return false;
901         }
902         return bindAppWidgetIdIfAllowed(appWidgetId, user.getIdentifier(), provider, options);
903     }
904 
905     /**
906      * Query if a given package was granted permission by the user to bind app widgets
907      *
908      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
909      *
910      * @param packageName The package for which the permission is being queried
911      * @param userId The user id of the user under which the package runs.
912      * @return true if the package was granted permission by the user to bind app widgets
913      * @hide
914      */
hasBindAppWidgetPermission(String packageName, int userId)915     public boolean hasBindAppWidgetPermission(String packageName, int userId) {
916         if (mService == null) {
917             return false;
918         }
919         try {
920             return mService.hasBindAppWidgetPermission(packageName, userId);
921         }
922         catch (RemoteException e) {
923             throw new RuntimeException("system server dead?", e);
924         }
925     }
926 
927     /**
928      * Query if a given package was granted permission by the user to bind app widgets
929      *
930      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
931      *
932      * @param packageName        The package for which the permission is being queried
933      * @return true if the package was granted permission by the user to bind app widgets
934      * @hide
935      */
hasBindAppWidgetPermission(String packageName)936     public boolean hasBindAppWidgetPermission(String packageName) {
937         if (mService == null) {
938             return false;
939         }
940         try {
941             return mService.hasBindAppWidgetPermission(packageName, UserHandle.myUserId());
942         }
943         catch (RemoteException e) {
944             throw new RuntimeException("system server dead?", e);
945         }
946     }
947 
948     /**
949      * Changes any user-granted permission for the given package to bind app widgets
950      *
951      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
952      *
953      * @param packageName The package whose permission is being changed
954      * @param permission Whether to give the package permission to bind widgets
955      *
956      * @hide
957      */
setBindAppWidgetPermission(String packageName, boolean permission)958     public void setBindAppWidgetPermission(String packageName, boolean permission) {
959         if (mService == null) {
960             return;
961         }
962         setBindAppWidgetPermission(packageName, UserHandle.myUserId(), permission);
963     }
964 
965     /**
966      * Changes any user-granted permission for the given package to bind app widgets
967      *
968      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
969      *
970      * @param packageName The package whose permission is being changed
971      * @param userId The user under which the package is running.
972      * @param permission Whether to give the package permission to bind widgets
973      *
974      * @hide
975      */
setBindAppWidgetPermission(String packageName, int userId, boolean permission)976     public void setBindAppWidgetPermission(String packageName, int userId, boolean permission) {
977         if (mService == null) {
978             return;
979         }
980         try {
981             mService.setBindAppWidgetPermission(packageName, userId, permission);
982         }
983         catch (RemoteException e) {
984             throw new RuntimeException("system server dead?", e);
985         }
986     }
987 
988     /**
989      * Binds the RemoteViewsService for a given appWidgetId and intent.
990      *
991      * The appWidgetId specified must already be bound to the calling AppWidgetHost via
992      * {@link android.appwidget.AppWidgetManager#bindAppWidgetId AppWidgetManager.bindAppWidgetId()}.
993      *
994      * @param packageName   The package from which the binding is requested.
995      * @param appWidgetId   The AppWidget instance for which to bind the RemoteViewsService.
996      * @param intent        The intent of the service which will be providing the data to the
997      *                      RemoteViewsAdapter.
998      * @param connection    The callback interface to be notified when a connection is made or lost.
999      * @hide
1000      */
bindRemoteViewsService(String packageName, int appWidgetId, Intent intent, IBinder connection)1001     public void bindRemoteViewsService(String packageName, int appWidgetId, Intent intent,
1002             IBinder connection) {
1003         if (mService == null) {
1004             return;
1005         }
1006         try {
1007             mService.bindRemoteViewsService(packageName, appWidgetId, intent, connection);
1008         }
1009         catch (RemoteException e) {
1010             throw new RuntimeException("system server dead?", e);
1011         }
1012     }
1013 
1014     /**
1015      * Unbinds the RemoteViewsService for a given appWidgetId and intent.
1016      *
1017      * The appWidgetId specified muse already be bound to the calling AppWidgetHost via
1018      * {@link android.appwidget.AppWidgetManager#bindAppWidgetId AppWidgetManager.bindAppWidgetId()}.
1019      *
1020      * @param packageName   The package from which the binding is requested.
1021      * @param appWidgetId   The AppWidget instance for which to bind the RemoteViewsService.
1022      * @param intent        The intent of the service which will be providing the data to the
1023      *                      RemoteViewsAdapter.
1024      * @hide
1025      */
unbindRemoteViewsService(String packageName, int appWidgetId, Intent intent)1026     public void unbindRemoteViewsService(String packageName, int appWidgetId, Intent intent) {
1027         if (mService == null) {
1028             return;
1029         }
1030         try {
1031             mService.unbindRemoteViewsService(packageName, appWidgetId, intent);
1032         }
1033         catch (RemoteException e) {
1034             throw new RuntimeException("system server dead?", e);
1035         }
1036     }
1037 
1038     /**
1039      * Get the list of appWidgetIds that have been bound to the given AppWidget
1040      * provider.
1041      *
1042      * @param provider The {@link android.content.BroadcastReceiver} that is the
1043      *            AppWidget provider to find appWidgetIds for.
1044      */
getAppWidgetIds(ComponentName provider)1045     public int[] getAppWidgetIds(ComponentName provider) {
1046         if (mService == null) {
1047             return new int[0];
1048         }
1049         try {
1050             return mService.getAppWidgetIds(provider);
1051         }
1052         catch (RemoteException e) {
1053             throw new RuntimeException("system server dead?", e);
1054         }
1055     }
1056 
1057     /**
1058      * @hide
1059      */
isBoundWidgetPackage(String packageName, int userId)1060     public boolean isBoundWidgetPackage(String packageName, int userId) {
1061         if (mService == null) {
1062             return false;
1063         }
1064         try {
1065             return mService.isBoundWidgetPackage(packageName, userId);
1066         } catch (RemoteException re) {
1067             throw new RuntimeException("system server dead?", re);
1068         }
1069     }
1070 
bindAppWidgetIdIfAllowed(int appWidgetId, int profileId, ComponentName provider, Bundle options)1071     private boolean bindAppWidgetIdIfAllowed(int appWidgetId, int profileId,
1072             ComponentName provider, Bundle options) {
1073         if (mService == null) {
1074             return false;
1075         }
1076         try {
1077             return mService.bindAppWidgetId(mPackageName, appWidgetId,
1078                     profileId, provider, options);
1079         }
1080         catch (RemoteException e) {
1081             throw new RuntimeException("system server dead?", e);
1082         }
1083     }
1084 
convertSizesToPixels(AppWidgetProviderInfo info)1085     private void convertSizesToPixels(AppWidgetProviderInfo info) {
1086         // Converting complex to dp.
1087         info.minWidth = TypedValue.complexToDimensionPixelSize(info.minWidth,
1088                 mDisplayMetrics);
1089         info.minHeight = TypedValue.complexToDimensionPixelSize(info.minHeight,
1090                 mDisplayMetrics);
1091         info.minResizeWidth = TypedValue.complexToDimensionPixelSize(info.minResizeWidth,
1092                 mDisplayMetrics);
1093         info.minResizeHeight = TypedValue.complexToDimensionPixelSize(info.minResizeHeight,
1094                 mDisplayMetrics);
1095     }
1096 }
1097