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