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