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