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