• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.appwidget;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.os.Bundle;
23 import android.os.IBinder;
24 import android.os.RemoteException;
25 import android.os.ServiceManager;
26 import android.os.UserHandle;
27 import android.util.DisplayMetrics;
28 import android.util.TypedValue;
29 import android.widget.RemoteViews;
30 
31 import com.android.internal.appwidget.IAppWidgetService;
32 
33 import java.lang.ref.WeakReference;
34 import java.util.List;
35 import java.util.WeakHashMap;
36 
37 /**
38  * Updates AppWidget state; gets information about installed AppWidget providers and other
39  * AppWidget related state.
40  *
41  * <div class="special reference">
42  * <h3>Developer Guides</h3>
43  * <p>For more information about creating app widgets, read the
44  * <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> developer guide.</p>
45  * </div>
46  */
47 public class AppWidgetManager {
48     static final String TAG = "AppWidgetManager";
49 
50     /**
51      * Send this from your {@link AppWidgetHost} activity when you want to pick an AppWidget to display.
52      * The AppWidget picker activity will be launched.
53      * <p>
54      * You must supply the following extras:
55      * <table>
56      *   <tr>
57      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
58      *     <td>A newly allocated appWidgetId, which will be bound to the AppWidget provider
59      *         once the user has selected one.</td>
60      *  </tr>
61      * </table>
62      *
63      * <p>
64      * The system will respond with an onActivityResult call with the following extras in
65      * the intent:
66      * <table>
67      *   <tr>
68      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
69      *     <td>The appWidgetId that you supplied in the original intent.</td>
70      *  </tr>
71      * </table>
72      * <p>
73      * When you receive the result from the AppWidget pick activity, if the resultCode is
74      * {@link android.app.Activity#RESULT_OK}, an AppWidget has been selected.  You should then
75      * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its configuration
76      * activity.  If {@link android.app.Activity#RESULT_CANCELED} is returned, you should delete
77      * the appWidgetId.
78      *
79      * @see #ACTION_APPWIDGET_CONFIGURE
80      */
81     public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
82 
83     /**
84      * Similar to ACTION_APPWIDGET_PICK, but used from keyguard
85      * @hide
86      */
87     public static final String
88             ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK";
89 
90     /**
91      * Send this from your {@link AppWidgetHost} activity when you want to bind an AppWidget to
92      * display and bindAppWidgetIdIfAllowed returns false.
93      * <p>
94      * You must supply the following extras:
95      * <table>
96      *   <tr>
97      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
98      *     <td>A newly allocated appWidgetId, which will be bound to the AppWidget provider
99      *         you provide.</td>
100      *  </tr>
101      *  <tr>
102      *     <td>{@link #EXTRA_APPWIDGET_PROVIDER}</td>
103      *     <td>The BroadcastReceiver that will be the AppWidget provider for this AppWidget.
104      *     </td>
105      *  </tr>
106      * </table>
107      *
108      * <p>
109      * The system will respond with an onActivityResult call with the following extras in
110      * the intent:
111      * <table>
112      *   <tr>
113      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
114      *     <td>The appWidgetId that you supplied in the original intent.</td>
115      *  </tr>
116      * </table>
117      * <p>
118      * When you receive the result from the AppWidget bind activity, if the resultCode is
119      * {@link android.app.Activity#RESULT_OK}, the AppWidget has been bound.  You should then
120      * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its
121      * configuration activity.  If {@link android.app.Activity#RESULT_CANCELED} is returned, you
122      * should delete
123      * the appWidgetId.
124      *
125      * @see #ACTION_APPWIDGET_CONFIGURE
126      *
127      */
128     public static final String ACTION_APPWIDGET_BIND = "android.appwidget.action.APPWIDGET_BIND";
129 
130     /**
131      * Sent when it is time to configure your AppWidget while it is being added to a host.
132      * This action is not sent as a broadcast to the AppWidget provider, but as a startActivity
133      * to the activity specified in the {@link AppWidgetProviderInfo AppWidgetProviderInfo meta-data}.
134      *
135      * <p>
136      * The intent will contain the following extras:
137      * <table>
138      *   <tr>
139      *     <td>{@link #EXTRA_APPWIDGET_ID}</td>
140      *     <td>The appWidgetId to configure.</td>
141      *  </tr>
142      * </table>
143      *
144      * <p>If you return {@link android.app.Activity#RESULT_OK} using
145      * {@link android.app.Activity#setResult Activity.setResult()}, the AppWidget will be added,
146      * and you will receive an {@link #ACTION_APPWIDGET_UPDATE} broadcast for this AppWidget.
147      * If you return {@link android.app.Activity#RESULT_CANCELED}, the host will cancel the add
148      * and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED} broadcast.
149      */
150     public static final String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE";
151 
152     /**
153      * An intent extra that contains one appWidgetId.
154      * <p>
155      * The value will be an int that can be retrieved like this:
156      * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java getExtra_EXTRA_APPWIDGET_ID}
157      */
158     public static final String EXTRA_APPWIDGET_ID = "appWidgetId";
159 
160     /**
161      * A bundle extra that contains the lower bound on the current width, in dips, of a widget instance.
162      */
163     public static final String OPTION_APPWIDGET_MIN_WIDTH = "appWidgetMinWidth";
164 
165     /**
166      * A bundle extra that contains the lower bound on the current height, in dips, of a widget instance.
167      */
168     public static final String OPTION_APPWIDGET_MIN_HEIGHT = "appWidgetMinHeight";
169 
170     /**
171      * A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
172      */
173     public static final String OPTION_APPWIDGET_MAX_WIDTH = "appWidgetMaxWidth";
174 
175     /**
176      * A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
177      */
178     public static final String OPTION_APPWIDGET_MAX_HEIGHT = "appWidgetMaxHeight";
179 
180     /**
181      * A bundle extra that hints to the AppWidgetProvider the category of host that owns this
182      * this widget. Can have the value {@link
183      * AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
184      * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}.
185      */
186     public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
187 
188     /**
189      * An intent extra which points to a bundle of extra information for a particular widget id.
190      * In particular this bundle can contain EXTRA_APPWIDGET_WIDTH and EXTRA_APPWIDGET_HEIGHT.
191      */
192     public static final String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions";
193 
194     /**
195      * An intent extra that contains multiple appWidgetIds.
196      * <p>
197      * The value will be an int array that can be retrieved like this:
198      * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java getExtra_EXTRA_APPWIDGET_IDS}
199      */
200     public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds";
201 
202     /**
203      * An intent extra that contains the component name of a AppWidget provider.
204      * <p>
205      * The value will be an ComponentName.
206      */
207     public static final String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider";
208 
209     /**
210      * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
211      * {@link AppWidgetProviderInfo} objects to mix in to the list of AppWidgets that are
212      * installed.  (This is how the launcher shows the search widget).
213      */
214     public static final String EXTRA_CUSTOM_INFO = "customInfo";
215 
216     /**
217      * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
218      * {@link android.os.Bundle} objects to mix in to the list of AppWidgets that are
219      * installed.  It will be added to the extras object on the {@link android.content.Intent}
220      * that is returned from the picker activity.
221      *
222      * {@more}
223      */
224     public static final String EXTRA_CUSTOM_EXTRAS = "customExtras";
225 
226     /**
227      * An intent extra to pass to the AppWidget picker which allows the picker to filter
228      * the list based on the {@link AppWidgetProviderInfo#widgetCategory}.
229      *
230      * @hide
231      */
232     public static final String EXTRA_CATEGORY_FILTER = "categoryFilter";
233 
234     /**
235      * An intent extra to pass to the AppWidget picker to specify whether or not to sort
236      * the list of caller-specified extra AppWidgets along with the rest of the AppWidgets
237      * @hide
238      */
239     public static final String EXTRA_CUSTOM_SORT = "customSort";
240 
241     /**
242      * A sentinel value that the AppWidget manager will never return as a appWidgetId.
243      */
244     public static final int INVALID_APPWIDGET_ID = 0;
245 
246     /**
247      * Sent when it is time to update your AppWidget.
248      *
249      * <p>This may be sent in response to a new instance for this AppWidget provider having
250      * been instantiated, the requested {@link AppWidgetProviderInfo#updatePeriodMillis update interval}
251      * having lapsed, or the system booting.
252      *
253      * <p>
254      * The intent will contain the following extras:
255      * <table>
256      *   <tr>
257      *     <td>{@link #EXTRA_APPWIDGET_IDS}</td>
258      *     <td>The appWidgetIds to update.  This may be all of the AppWidgets created for this
259      *     provider, or just a subset.  The system tries to send updates for as few AppWidget
260      *     instances as possible.</td>
261      *  </tr>
262      * </table>
263      *
264      * @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
265      */
266     public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";
267 
268     /**
269      * Sent when the custom extras for an AppWidget change.
270      *
271      * @see AppWidgetProvider#onAppWidgetOptionsChanged
272      *      AppWidgetProvider.onAppWidgetOptionsChanged(Context context,
273      *      AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras)
274      */
275     public static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS";
276 
277     /**
278      * Sent when an instance of an AppWidget is deleted from its host.
279      *
280      * @see AppWidgetProvider#onDeleted AppWidgetProvider.onDeleted(Context context, int[] appWidgetIds)
281      */
282     public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED";
283 
284     /**
285      * Sent when an instance of an AppWidget is removed from the last host.
286      *
287      * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
288      */
289     public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED";
290 
291     /**
292      * Sent when an instance of an AppWidget is added to a host for the first time.
293      * This broadcast is sent at boot time if there is a AppWidgetHost installed with
294      * an instance for this provider.
295      *
296      * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
297      */
298     public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED";
299 
300     /**
301      * Field for the manifest meta-data tag.
302      *
303      * @see AppWidgetProviderInfo
304      */
305     public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";
306 
307     static WeakHashMap<Context, WeakReference<AppWidgetManager>> sManagerCache =
308         new WeakHashMap<Context, WeakReference<AppWidgetManager>>();
309     static IAppWidgetService sService;
310 
311     Context mContext;
312 
313     private DisplayMetrics mDisplayMetrics;
314 
315     /**
316      * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context
317      * Context} object.
318      */
getInstance(Context context)319     public static AppWidgetManager getInstance(Context context) {
320         synchronized (sManagerCache) {
321             if (sService == null) {
322                 IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE);
323                 sService = IAppWidgetService.Stub.asInterface(b);
324             }
325 
326             WeakReference<AppWidgetManager> ref = sManagerCache.get(context);
327             AppWidgetManager result = null;
328             if (ref != null) {
329                 result = ref.get();
330             }
331             if (result == null) {
332                 result = new AppWidgetManager(context);
333                 sManagerCache.put(context, new WeakReference<AppWidgetManager>(result));
334             }
335             return result;
336         }
337     }
338 
AppWidgetManager(Context context)339     private AppWidgetManager(Context context) {
340         mContext = context;
341         mDisplayMetrics = context.getResources().getDisplayMetrics();
342     }
343 
344     /**
345      * Set the RemoteViews to use for the specified appWidgetIds.
346      *
347      * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should
348      * contain a complete representation of the widget. For performing partial widget updates, see
349      * {@link #partiallyUpdateAppWidget(int[], RemoteViews)}.
350      *
351      * <p>
352      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
353      * and outside of the handler.
354      * This method will only work when called from the uid that owns the AppWidget provider.
355      *
356      * <p>
357      * The total Bitmap memory used by the RemoteViews object cannot exceed that required to
358      * fill the screen 1.5 times, ie. (screen width x screen height x 4 x 1.5) bytes.
359      *
360      * @param appWidgetIds     The AppWidget instances for which to set the RemoteViews.
361      * @param views         The RemoteViews object to show.
362      */
updateAppWidget(int[] appWidgetIds, RemoteViews views)363     public void updateAppWidget(int[] appWidgetIds, RemoteViews views) {
364         try {
365             sService.updateAppWidgetIds(appWidgetIds, views);
366         }
367         catch (RemoteException e) {
368             throw new RuntimeException("system server dead?", e);
369         }
370     }
371 
372     /**
373      * Update the extras for a given widget instance.
374      *
375      * The extras can be used to embed additional information about this widget to be accessed
376      * by the associated widget's AppWidgetProvider.
377      *
378      * @see #getAppWidgetOptions(int)
379      *
380      * @param appWidgetId    The AppWidget instances for which to set the RemoteViews.
381      * @param options         The options to associate with this widget
382      */
updateAppWidgetOptions(int appWidgetId, Bundle options)383     public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
384         try {
385             sService.updateAppWidgetOptions(appWidgetId, options);
386         }
387         catch (RemoteException e) {
388             throw new RuntimeException("system server dead?", e);
389         }
390     }
391 
392     /**
393      * Get the extras associated with a given widget instance.
394      *
395      * The extras can be used to embed additional information about this widget to be accessed
396      * by the associated widget's AppWidgetProvider.
397      *
398      * @see #updateAppWidgetOptions(int, Bundle)
399      *
400      * @param appWidgetId     The AppWidget instances for which to set the RemoteViews.
401      * @return                The options associated with the given widget instance.
402      */
getAppWidgetOptions(int appWidgetId)403     public Bundle getAppWidgetOptions(int appWidgetId) {
404         try {
405             return sService.getAppWidgetOptions(appWidgetId);
406         }
407         catch (RemoteException e) {
408             throw new RuntimeException("system server dead?", e);
409         }
410     }
411 
412     /**
413      * Set the RemoteViews to use for the specified appWidgetId.
414      *
415      * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should
416      * contain a complete representation of the widget. For performing partial widget updates, see
417      * {@link #partiallyUpdateAppWidget(int, RemoteViews)}.
418      *
419      * <p>
420      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
421      * and outside of the handler.
422      * This method will only work when called from the uid that owns the AppWidget provider.
423      *
424      * <p>
425      * The total Bitmap memory used by the RemoteViews object cannot exceed that required to
426      * fill the screen 1.5 times, ie. (screen width x screen height x 4 x 1.5) bytes.
427      *
428      * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
429      * @param views         The RemoteViews object to show.
430      */
updateAppWidget(int appWidgetId, RemoteViews views)431     public void updateAppWidget(int appWidgetId, RemoteViews views) {
432         updateAppWidget(new int[] { appWidgetId }, views);
433     }
434 
435     /**
436      * Perform an incremental update or command on the widget(s) specified by appWidgetIds.
437      *
438      * This update  differs from {@link #updateAppWidget(int[], RemoteViews)} in that the
439      * RemoteViews object which is passed is understood to be an incomplete representation of the
440      * widget, and hence does not replace the cached representation of the widget. As of API
441      * level 17, the new properties set within the views objects will be appended to the cached
442      * representation of the widget, and hence will persist.
443      *
444      * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
445      * {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
446      *
447      * <p>
448      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
449      * and outside of the handler.
450      * This method will only work when called from the uid that owns the AppWidget provider.
451      *
452      * <p>
453      * This method will be ignored if a widget has not received a full update via
454      * {@link #updateAppWidget(int[], RemoteViews)}.
455      *
456      * @param appWidgetIds     The AppWidget instances for which to set the RemoteViews.
457      * @param views            The RemoteViews object containing the incremental update / command.
458      */
partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views)459     public void partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views) {
460         try {
461             sService.partiallyUpdateAppWidgetIds(appWidgetIds, views);
462         } catch (RemoteException e) {
463             throw new RuntimeException("system server dead?", e);
464         }
465     }
466 
467     /**
468      * Perform an incremental update or command on the widget specified by appWidgetId.
469      *
470      * This update  differs from {@link #updateAppWidget(int, RemoteViews)} in that the RemoteViews
471      * object which is passed is understood to be an incomplete representation of the widget, and
472      * hence is not cached by the AppWidgetService. Note that because these updates are not cached,
473      * any state that they modify that is not restored by restoreInstanceState will not persist in
474      * the case that the widgets are restored using the cached version in AppWidgetService.
475      *
476      * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
477      * {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
478      *
479      * <p>
480      * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
481      * and outside of the handler.
482      * This method will only work when called from the uid that owns the AppWidget provider.
483      *
484      * <p>
485      * This method will be ignored if a widget has not received a full update via
486      * {@link #updateAppWidget(int[], RemoteViews)}.
487      *
488      * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
489      * @param views            The RemoteViews object containing the incremental update / command.
490      */
partiallyUpdateAppWidget(int appWidgetId, RemoteViews views)491     public void partiallyUpdateAppWidget(int appWidgetId, RemoteViews views) {
492         partiallyUpdateAppWidget(new int[] { appWidgetId }, views);
493     }
494 
495     /**
496      * Set the RemoteViews to use for all AppWidget instances for the supplied AppWidget provider.
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      * @param provider      The {@link ComponentName} for the {@link
504      * android.content.BroadcastReceiver BroadcastReceiver} provider
505      *                      for your AppWidget.
506      * @param views         The RemoteViews object to show.
507      */
updateAppWidget(ComponentName provider, RemoteViews views)508     public void updateAppWidget(ComponentName provider, RemoteViews views) {
509         try {
510             sService.updateAppWidgetProvider(provider, views);
511         }
512         catch (RemoteException e) {
513             throw new RuntimeException("system server dead?", e);
514         }
515     }
516 
517     /**
518      * Notifies the specified collection view in all the specified AppWidget instances
519      * to invalidate their currently data.
520      *
521      * @param appWidgetIds  The AppWidget instances for which to notify of view data changes.
522      * @param viewId        The collection view id.
523      */
notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId)524     public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
525         try {
526             sService.notifyAppWidgetViewDataChanged(appWidgetIds, viewId);
527         }
528         catch (RemoteException e) {
529             throw new RuntimeException("system server dead?", e);
530         }
531     }
532 
533     /**
534      * Notifies the specified collection view in all the specified AppWidget instance
535      * to invalidate it's currently data.
536      *
537      * @param appWidgetId  The AppWidget instance for which to notify of view data changes.
538      * @param viewId        The collection view id.
539      */
notifyAppWidgetViewDataChanged(int appWidgetId, int viewId)540     public void notifyAppWidgetViewDataChanged(int appWidgetId, int viewId) {
541         notifyAppWidgetViewDataChanged(new int[] { appWidgetId }, viewId);
542     }
543 
544     /**
545      * Return a list of the AppWidget providers that are currently installed.
546      */
getInstalledProviders()547     public List<AppWidgetProviderInfo> getInstalledProviders() {
548         return getInstalledProviders(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
549     }
550 
551     /**
552      * Return a list of the AppWidget providers that are currently installed.
553      *
554      * @param categoryFilter Will only return providers which register as any of the specified
555      *        specified categories. See {@link AppWidgetProviderInfo#widgetCategory}.
556      * @hide
557      */
getInstalledProviders(int categoryFilter)558     public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
559         try {
560             List<AppWidgetProviderInfo> providers = sService.getInstalledProviders(categoryFilter);
561             for (AppWidgetProviderInfo info : providers) {
562                 // Converting complex to dp.
563                 info.minWidth =
564                         TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics);
565                 info.minHeight =
566                         TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics);
567                 info.minResizeWidth =
568                     TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics);
569                 info.minResizeHeight =
570                     TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics);
571             }
572             return providers;
573         }
574         catch (RemoteException e) {
575             throw new RuntimeException("system server dead?", e);
576         }
577     }
578 
579     /**
580      * Get the available info about the AppWidget.
581      *
582      * @return A appWidgetId.  If the appWidgetId has not been bound to a provider yet, or
583      * you don't have access to that appWidgetId, null is returned.
584      */
getAppWidgetInfo(int appWidgetId)585     public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
586         try {
587             AppWidgetProviderInfo info = sService.getAppWidgetInfo(appWidgetId);
588             if (info != null) {
589                 // Converting complex to dp.
590                 info.minWidth =
591                         TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics);
592                 info.minHeight =
593                         TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics);
594                 info.minResizeWidth =
595                     TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics);
596                 info.minResizeHeight =
597                     TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics);
598             }
599             return info;
600         }
601         catch (RemoteException e) {
602             throw new RuntimeException("system server dead?", e);
603         }
604     }
605 
606     /**
607      * Set the component for a given appWidgetId.
608      *
609      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
610      *         widgets always for your component. This method is used by the AppWidget picker and
611      *         should not be used by other apps.
612      *
613      * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
614      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
615      *                      provider for this AppWidget.
616      * @hide
617      */
bindAppWidgetId(int appWidgetId, ComponentName provider)618     public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
619         try {
620             sService.bindAppWidgetId(appWidgetId, provider, null);
621         }
622         catch (RemoteException e) {
623             throw new RuntimeException("system server dead?", e);
624         }
625     }
626 
627     /**
628      * Set the component for a given appWidgetId.
629      *
630      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
631      *         widgets always for your component. This method is used by the AppWidget picker and
632      *         should not be used by other apps.
633      *
634      * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
635      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
636      *                      provider for this AppWidget.
637      * @param options       Bundle containing options for the AppWidget. See also
638      *                      {@link #updateAppWidgetOptions(int, Bundle)}
639      *
640      * @hide
641      */
bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options)642     public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
643         try {
644             sService.bindAppWidgetId(appWidgetId, provider, options);
645         }
646         catch (RemoteException e) {
647             throw new RuntimeException("system server dead?", e);
648         }
649     }
650 
651     /**
652      * Set the component for a given appWidgetId.
653      *
654      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
655      *         widgets always for your component. Should be used by apps that host widgets; if this
656      *         method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to
657      *         bind
658      *
659      * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
660      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
661      *                      provider for this AppWidget.
662      * @return true if this component has permission to bind the AppWidget
663      */
bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider)664     public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider) {
665         if (mContext == null) {
666             return false;
667         }
668         try {
669             return sService.bindAppWidgetIdIfAllowed(
670                     mContext.getPackageName(), appWidgetId, provider, null);
671         }
672         catch (RemoteException e) {
673             throw new RuntimeException("system server dead?", e);
674         }
675     }
676 
677     /**
678      * Set the component for a given appWidgetId.
679      *
680      * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
681      *         widgets always for your component. Should be used by apps that host widgets; if this
682      *         method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to
683      *         bind
684      *
685      * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
686      * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
687      *                      provider for this AppWidget.
688      * @param options       Bundle containing options for the AppWidget. See also
689      *                      {@link #updateAppWidgetOptions(int, Bundle)}
690      *
691      * @return true if this component has permission to bind the AppWidget
692      */
bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider, Bundle options)693     public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider,
694             Bundle options) {
695         if (mContext == null) {
696             return false;
697         }
698         try {
699             return sService.bindAppWidgetIdIfAllowed(
700                     mContext.getPackageName(), appWidgetId, provider, options);
701         }
702         catch (RemoteException e) {
703             throw new RuntimeException("system server dead?", e);
704         }
705     }
706 
707     /**
708      * Query if a given package was granted permission by the user to bind app widgets
709      *
710      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
711      *
712      * @param packageName        The package for which the permission is being queried
713      * @return true if the package was granted permission by the user to bind app widgets
714      * @hide
715      */
hasBindAppWidgetPermission(String packageName)716     public boolean hasBindAppWidgetPermission(String packageName) {
717         try {
718             return sService.hasBindAppWidgetPermission(packageName);
719         }
720         catch (RemoteException e) {
721             throw new RuntimeException("system server dead?", e);
722         }
723     }
724 
725     /**
726      * Changes any user-granted permission for the given package to bind app widgets
727      *
728      * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission
729      *
730      * @param provider        The package whose permission is being changed
731      * @param permission      Whether to give the package permission to bind widgets
732      * @hide
733      */
setBindAppWidgetPermission(String packageName, boolean permission)734     public void setBindAppWidgetPermission(String packageName, boolean permission) {
735         try {
736             sService.setBindAppWidgetPermission(packageName, permission);
737         }
738         catch (RemoteException e) {
739             throw new RuntimeException("system server dead?", e);
740         }
741     }
742 
743     /**
744      * Binds the RemoteViewsService for a given appWidgetId and intent.
745      *
746      * The appWidgetId specified must already be bound to the calling AppWidgetHost via
747      * {@link android.appwidget.AppWidgetManager#bindAppWidgetId AppWidgetManager.bindAppWidgetId()}.
748      *
749      * @param appWidgetId   The AppWidget instance for which to bind the RemoteViewsService.
750      * @param intent        The intent of the service which will be providing the data to the
751      *                      RemoteViewsAdapter.
752      * @param connection    The callback interface to be notified when a connection is made or lost.
753      * @param userHandle    The user to bind to.
754      * @hide
755      */
bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection, UserHandle userHandle)756     public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection,
757             UserHandle userHandle) {
758         try {
759             sService.bindRemoteViewsService(appWidgetId, intent, connection,
760                     userHandle.getIdentifier());
761         }
762         catch (RemoteException e) {
763             throw new RuntimeException("system server dead?", e);
764         }
765     }
766 
767     /**
768      * Unbinds the RemoteViewsService for a given appWidgetId and intent.
769      *
770      * The appWidgetId specified muse already be bound to the calling AppWidgetHost via
771      * {@link android.appwidget.AppWidgetManager#bindAppWidgetId AppWidgetManager.bindAppWidgetId()}.
772      *
773      * @param appWidgetId   The AppWidget instance for which to bind the RemoteViewsService.
774      * @param intent        The intent of the service which will be providing the data to the
775      *                      RemoteViewsAdapter.
776      * @param userHandle    The user to unbind from.
777      * @hide
778      */
unbindRemoteViewsService(int appWidgetId, Intent intent, UserHandle userHandle)779     public void unbindRemoteViewsService(int appWidgetId, Intent intent, UserHandle userHandle) {
780         try {
781             sService.unbindRemoteViewsService(appWidgetId, intent, userHandle.getIdentifier());
782         }
783         catch (RemoteException e) {
784             throw new RuntimeException("system server dead?", e);
785         }
786     }
787 
788     /**
789      * Get the list of appWidgetIds that have been bound to the given AppWidget
790      * provider.
791      *
792      * @param provider The {@link android.content.BroadcastReceiver} that is the
793      *            AppWidget provider to find appWidgetIds for.
794      */
getAppWidgetIds(ComponentName provider)795     public int[] getAppWidgetIds(ComponentName provider) {
796         try {
797             return sService.getAppWidgetIds(provider);
798         }
799         catch (RemoteException e) {
800             throw new RuntimeException("system server dead?", e);
801         }
802     }
803 }
804 
805