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