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