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