1 /* 2 * Copyright (C) 2016 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 package android.content.pm; 17 18 import android.Manifest; 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.RequiresPermission; 22 import android.annotation.SystemApi; 23 import android.annotation.SystemService; 24 import android.annotation.TestApi; 25 import android.annotation.UnsupportedAppUsage; 26 import android.annotation.UserIdInt; 27 import android.app.usage.UsageStatsManager; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.IntentFilter; 32 import android.content.IntentSender; 33 import android.graphics.drawable.AdaptiveIconDrawable; 34 import android.os.Build; 35 import android.os.Build.VERSION_CODES; 36 import android.os.Parcel; 37 import android.os.Parcelable; 38 import android.os.RemoteException; 39 import android.os.ServiceManager; 40 41 import com.android.internal.annotations.VisibleForTesting; 42 43 import java.util.List; 44 45 /** 46 * <p><code>ShortcutManager</code> executes operations on an app's set of <i>shortcuts</i>, which 47 * represent specific tasks and actions that users can perform within your app. This page lists 48 * components of the <code>ShortcutManager</code> class that you can use to create and manage 49 * sets of shortcuts. 50 * 51 * <p>To learn about methods that retrieve information about a single shortcut—including 52 * identifiers, type, and status—read the <code> 53 * <a href="/reference/android/content/pm/ShortcutInfo.html">ShortcutInfo</a></code> reference. 54 * 55 * <p>For guidance about using shortcuts, see 56 * <a href="/guide/topics/ui/shortcuts/index.html">App shortcuts</a>. 57 * 58 * <h3>Retrieving class instances</h3> 59 * <!-- Provides a heading for the content filled in by the @SystemService annotation below --> 60 */ 61 @SystemService(Context.SHORTCUT_SERVICE) 62 public class ShortcutManager { 63 private static final String TAG = "ShortcutManager"; 64 65 private final Context mContext; 66 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 67 private final IShortcutService mService; 68 69 /** 70 * @hide 71 */ ShortcutManager(Context context, IShortcutService service)72 public ShortcutManager(Context context, IShortcutService service) { 73 mContext = context; 74 mService = service; 75 } 76 77 /** 78 * @hide 79 */ 80 @TestApi ShortcutManager(Context context)81 public ShortcutManager(Context context) { 82 this(context, IShortcutService.Stub.asInterface( 83 ServiceManager.getService(Context.SHORTCUT_SERVICE))); 84 } 85 86 /** 87 * Publish the list of shortcuts. All existing dynamic shortcuts from the caller app 88 * will be replaced. If there are already pinned shortcuts with the same IDs, 89 * the mutable pinned shortcuts are updated. 90 * 91 * <p>This API will be rate-limited. 92 * 93 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited. 94 * 95 * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded, 96 * or when trying to update immutable shortcuts. 97 * 98 * @throws IllegalStateException when the user is locked. 99 */ setDynamicShortcuts(@onNull List<ShortcutInfo> shortcutInfoList)100 public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) { 101 try { 102 return mService.setDynamicShortcuts(mContext.getPackageName(), 103 new ParceledListSlice(shortcutInfoList), injectMyUserId()); 104 } catch (RemoteException e) { 105 throw e.rethrowFromSystemServer(); 106 } 107 } 108 109 /** 110 * Return all dynamic shortcuts from the caller app. 111 * 112 * <p>This API is intended to be used for examining what shortcuts are currently published. 113 * Re-publishing returned {@link ShortcutInfo}s via APIs such as 114 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons. 115 * 116 * @throws IllegalStateException when the user is locked. 117 */ 118 @NonNull getDynamicShortcuts()119 public List<ShortcutInfo> getDynamicShortcuts() { 120 try { 121 return mService.getDynamicShortcuts(mContext.getPackageName(), injectMyUserId()) 122 .getList(); 123 } catch (RemoteException e) { 124 throw e.rethrowFromSystemServer(); 125 } 126 } 127 128 /** 129 * Return all static (manifest) shortcuts from the caller app. 130 * 131 * <p>This API is intended to be used for examining what shortcuts are currently published. 132 * Re-publishing returned {@link ShortcutInfo}s via APIs such as 133 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons. 134 * 135 * @throws IllegalStateException when the user is locked. 136 */ 137 @NonNull getManifestShortcuts()138 public List<ShortcutInfo> getManifestShortcuts() { 139 try { 140 return mService.getManifestShortcuts(mContext.getPackageName(), injectMyUserId()) 141 .getList(); 142 } catch (RemoteException e) { 143 throw e.rethrowFromSystemServer(); 144 } 145 } 146 147 /** 148 * Publish the list of dynamic shortcuts. If there are already dynamic or pinned shortcuts with 149 * the same IDs, each mutable shortcut is updated. 150 * 151 * <p>This API will be rate-limited. 152 * 153 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited. 154 * 155 * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded, 156 * or when trying to update immutable shortcuts. 157 * 158 * @throws IllegalStateException when the user is locked. 159 */ addDynamicShortcuts(@onNull List<ShortcutInfo> shortcutInfoList)160 public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) { 161 try { 162 return mService.addDynamicShortcuts(mContext.getPackageName(), 163 new ParceledListSlice(shortcutInfoList), injectMyUserId()); 164 } catch (RemoteException e) { 165 throw e.rethrowFromSystemServer(); 166 } 167 } 168 169 /** 170 * Delete dynamic shortcuts by ID. 171 * 172 * @throws IllegalStateException when the user is locked. 173 */ removeDynamicShortcuts(@onNull List<String> shortcutIds)174 public void removeDynamicShortcuts(@NonNull List<String> shortcutIds) { 175 try { 176 mService.removeDynamicShortcuts(mContext.getPackageName(), shortcutIds, 177 injectMyUserId()); 178 } catch (RemoteException e) { 179 throw e.rethrowFromSystemServer(); 180 } 181 } 182 183 /** 184 * Delete all dynamic shortcuts from the caller app. 185 * 186 * @throws IllegalStateException when the user is locked. 187 */ removeAllDynamicShortcuts()188 public void removeAllDynamicShortcuts() { 189 try { 190 mService.removeAllDynamicShortcuts(mContext.getPackageName(), injectMyUserId()); 191 } catch (RemoteException e) { 192 throw e.rethrowFromSystemServer(); 193 } 194 } 195 196 /** 197 * Return all pinned shortcuts from the caller app. 198 * 199 * <p>This API is intended to be used for examining what shortcuts are currently published. 200 * Re-publishing returned {@link ShortcutInfo}s via APIs such as 201 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons. 202 * 203 * @throws IllegalStateException when the user is locked. 204 */ 205 @NonNull getPinnedShortcuts()206 public List<ShortcutInfo> getPinnedShortcuts() { 207 try { 208 return mService.getPinnedShortcuts(mContext.getPackageName(), injectMyUserId()) 209 .getList(); 210 } catch (RemoteException e) { 211 throw e.rethrowFromSystemServer(); 212 } 213 } 214 215 /** 216 * Update all existing shortcuts with the same IDs. Target shortcuts may be pinned and/or 217 * dynamic, but they must not be immutable. 218 * 219 * <p>This API will be rate-limited. 220 * 221 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited. 222 * 223 * @throws IllegalArgumentException If trying to update immutable shortcuts. 224 * 225 * @throws IllegalStateException when the user is locked. 226 */ updateShortcuts(@onNull List<ShortcutInfo> shortcutInfoList)227 public boolean updateShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) { 228 try { 229 return mService.updateShortcuts(mContext.getPackageName(), 230 new ParceledListSlice(shortcutInfoList), injectMyUserId()); 231 } catch (RemoteException e) { 232 throw e.rethrowFromSystemServer(); 233 } 234 } 235 236 /** 237 * Disable pinned shortcuts. For more details, read 238 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts"> 239 * Disable shortcuts</a>. 240 * 241 * @throws IllegalArgumentException If trying to disable immutable shortcuts. 242 * 243 * @throws IllegalStateException when the user is locked. 244 */ disableShortcuts(@onNull List<String> shortcutIds)245 public void disableShortcuts(@NonNull List<String> shortcutIds) { 246 try { 247 mService.disableShortcuts(mContext.getPackageName(), shortcutIds, 248 /* disabledMessage =*/ null, /* disabledMessageResId =*/ 0, 249 injectMyUserId()); 250 } catch (RemoteException e) { 251 throw e.rethrowFromSystemServer(); 252 } 253 } 254 255 /** 256 * @hide old signature, kept for unit testing. 257 */ disableShortcuts(@onNull List<String> shortcutIds, int disabledMessageResId)258 public void disableShortcuts(@NonNull List<String> shortcutIds, int disabledMessageResId) { 259 try { 260 mService.disableShortcuts(mContext.getPackageName(), shortcutIds, 261 /* disabledMessage =*/ null, disabledMessageResId, 262 injectMyUserId()); 263 } catch (RemoteException e) { 264 throw e.rethrowFromSystemServer(); 265 } 266 } 267 268 /** 269 * @hide old signature, kept for unit testing. 270 */ disableShortcuts(@onNull List<String> shortcutIds, String disabledMessage)271 public void disableShortcuts(@NonNull List<String> shortcutIds, String disabledMessage) { 272 disableShortcuts(shortcutIds, (CharSequence) disabledMessage); 273 } 274 275 /** 276 * Disable pinned shortcuts, showing the user a custom error message when they try to select 277 * the disabled shortcuts. 278 * For more details, read 279 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts"> 280 * Disable shortcuts</a>. 281 * 282 * @throws IllegalArgumentException If trying to disable immutable shortcuts. 283 * 284 * @throws IllegalStateException when the user is locked. 285 */ disableShortcuts(@onNull List<String> shortcutIds, CharSequence disabledMessage)286 public void disableShortcuts(@NonNull List<String> shortcutIds, CharSequence disabledMessage) { 287 try { 288 mService.disableShortcuts(mContext.getPackageName(), shortcutIds, 289 disabledMessage, /* disabledMessageResId =*/ 0, 290 injectMyUserId()); 291 } catch (RemoteException e) { 292 throw e.rethrowFromSystemServer(); 293 } 294 } 295 296 /** 297 * Re-enable pinned shortcuts that were previously disabled. If the target shortcuts 298 * are already enabled, this method does nothing. 299 * 300 * @throws IllegalArgumentException If trying to enable immutable shortcuts. 301 * 302 * @throws IllegalStateException when the user is locked. 303 */ enableShortcuts(@onNull List<String> shortcutIds)304 public void enableShortcuts(@NonNull List<String> shortcutIds) { 305 try { 306 mService.enableShortcuts(mContext.getPackageName(), shortcutIds, injectMyUserId()); 307 } catch (RemoteException e) { 308 throw e.rethrowFromSystemServer(); 309 } 310 } 311 312 313 /** 314 * @hide old signature, kept for unit testing. 315 */ getMaxShortcutCountForActivity()316 public int getMaxShortcutCountForActivity() { 317 return getMaxShortcutCountPerActivity(); 318 } 319 320 /** 321 * Return the maximum number of static and dynamic shortcuts that each launcher icon 322 * can have at a time. 323 */ getMaxShortcutCountPerActivity()324 public int getMaxShortcutCountPerActivity() { 325 try { 326 return mService.getMaxShortcutCountPerActivity( 327 mContext.getPackageName(), injectMyUserId()); 328 } catch (RemoteException e) { 329 throw e.rethrowFromSystemServer(); 330 } 331 } 332 333 /** 334 * Return the number of times the caller app can call the rate-limited APIs 335 * before the rate limit counter is reset. 336 * 337 * @see #getRateLimitResetTime() 338 * 339 * @hide 340 */ getRemainingCallCount()341 public int getRemainingCallCount() { 342 try { 343 return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId()); 344 } catch (RemoteException e) { 345 throw e.rethrowFromSystemServer(); 346 } 347 } 348 349 /** 350 * Return when the rate limit count will be reset next time, in milliseconds since the epoch. 351 * 352 * @see #getRemainingCallCount() 353 * @see System#currentTimeMillis() 354 * 355 * @hide 356 */ getRateLimitResetTime()357 public long getRateLimitResetTime() { 358 try { 359 return mService.getRateLimitResetTime(mContext.getPackageName(), injectMyUserId()); 360 } catch (RemoteException e) { 361 throw e.rethrowFromSystemServer(); 362 } 363 } 364 365 /** 366 * Return {@code true} when rate-limiting is active for the caller app. 367 * 368 * <p>For details, see <a href="/guide/topics/ui/shortcuts/managing-shortcuts#rate-limiting"> 369 * Rate limiting</a>. 370 * 371 * @throws IllegalStateException when the user is locked. 372 */ isRateLimitingActive()373 public boolean isRateLimitingActive() { 374 try { 375 return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId()) 376 == 0; 377 } catch (RemoteException e) { 378 throw e.rethrowFromSystemServer(); 379 } 380 } 381 382 /** 383 * Return the max width for icons, in pixels. 384 * 385 * <p> Note that this method returns max width of icon's visible part. Hence, it does not take 386 * into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image 387 * to function as {@link AdaptiveIconDrawable}, multiply 388 * 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size. 389 */ getIconMaxWidth()390 public int getIconMaxWidth() { 391 try { 392 // TODO Implement it properly using xdpi. 393 return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId()); 394 } catch (RemoteException e) { 395 throw e.rethrowFromSystemServer(); 396 } 397 } 398 399 /** 400 * Return the max height for icons, in pixels. 401 */ getIconMaxHeight()402 public int getIconMaxHeight() { 403 try { 404 // TODO Implement it properly using ydpi. 405 return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId()); 406 } catch (RemoteException e) { 407 throw e.rethrowFromSystemServer(); 408 } 409 } 410 411 /** 412 * Apps that publish shortcuts should call this method whenever the user 413 * selects the shortcut containing the given ID or when the user completes 414 * an action in the app that is equivalent to selecting the shortcut. 415 * For more details, read about 416 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#track-usage"> 417 * tracking shortcut usage</a>. 418 * 419 * <p>The information is accessible via {@link UsageStatsManager#queryEvents} 420 * Typically, launcher apps use this information to build a prediction model 421 * so that they can promote the shortcuts that are likely to be used at the moment. 422 * 423 * @throws IllegalStateException when the user is locked. 424 */ reportShortcutUsed(String shortcutId)425 public void reportShortcutUsed(String shortcutId) { 426 try { 427 mService.reportShortcutUsed(mContext.getPackageName(), shortcutId, 428 injectMyUserId()); 429 } catch (RemoteException e) { 430 throw e.rethrowFromSystemServer(); 431 } 432 } 433 434 /** 435 * Return {@code TRUE} if the app is running on a device whose default launcher supports 436 * {@link #requestPinShortcut(ShortcutInfo, IntentSender)}. 437 * 438 * <p>The return value may change in subsequent calls if the user changes the default launcher 439 * app. 440 * 441 * <p><b>Note:</b> See also the support library counterpart 442 * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported( 443 * Context)}, which supports Android versions lower than {@link VERSION_CODES#O} using the 444 * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}. 445 * 446 * @see #requestPinShortcut(ShortcutInfo, IntentSender) 447 */ isRequestPinShortcutSupported()448 public boolean isRequestPinShortcutSupported() { 449 try { 450 return mService.isRequestPinItemSupported(injectMyUserId(), 451 LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT); 452 } catch (RemoteException e) { 453 throw e.rethrowFromSystemServer(); 454 } 455 } 456 457 /** 458 * Request to create a pinned shortcut. The default launcher will receive this request and 459 * ask the user for approval. If the user approves it, the shortcut will be created, and 460 * {@code resultIntent} will be sent. If a request is denied by the user, however, no response 461 * will be sent to the caller. 462 * 463 * <p>Only apps with a foreground activity or a foreground service can call this method. 464 * Otherwise, it'll throw {@link IllegalStateException}. 465 * 466 * <p>It's up to the launcher to decide how to handle previous pending requests when the same 467 * package calls this API multiple times in a row. One possible strategy is to ignore any 468 * previous requests. 469 * 470 * <p><b>Note:</b> See also the support library counterpart 471 * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut( 472 * Context, ShortcutInfoCompat, IntentSender)}, 473 * which supports Android versions lower than {@link VERSION_CODES#O} using the 474 * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}. 475 * 476 * @param shortcut Shortcut to pin. If an app wants to pin an existing (either static 477 * or dynamic) shortcut, then it only needs to have an ID. Although other fields don't have 478 * to be set, the target shortcut must be enabled. 479 * 480 * <p>If it's a new shortcut, all the mandatory fields, such as a short label, must be 481 * set. 482 * @param resultIntent If not null, this intent will be sent when the shortcut is pinned. 483 * Use {@link android.app.PendingIntent#getIntentSender()} to create an {@link IntentSender}. 484 * To avoid background execution limits, use an unexported, manifest-declared receiver. 485 * For more details, see 486 * <a href="/guide/topics/ui/shortcuts/creating-shortcuts.html#pinned"> 487 * Creating pinned shortcuts</a>. 488 * 489 * @return {@code TRUE} if the launcher supports this feature. Note the API will return without 490 * waiting for the user to respond, so getting {@code TRUE} from this API does *not* mean 491 * the shortcut was pinned successfully. {@code FALSE} if the launcher doesn't support this 492 * feature. 493 * 494 * @see #isRequestPinShortcutSupported() 495 * @see IntentSender 496 * @see android.app.PendingIntent#getIntentSender() 497 * 498 * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled. 499 * @throws IllegalStateException The caller doesn't have a foreground activity or a foreground 500 * service, or the device is locked. 501 */ requestPinShortcut(@onNull ShortcutInfo shortcut, @Nullable IntentSender resultIntent)502 public boolean requestPinShortcut(@NonNull ShortcutInfo shortcut, 503 @Nullable IntentSender resultIntent) { 504 try { 505 return mService.requestPinShortcut(mContext.getPackageName(), shortcut, 506 resultIntent, injectMyUserId()); 507 } catch (RemoteException e) { 508 throw e.rethrowFromSystemServer(); 509 } 510 } 511 512 /** 513 * Returns an Intent which can be used by the default launcher to pin a shortcut containing the 514 * given {@link ShortcutInfo}. This method should be used by an Activity to set a result in 515 * response to {@link Intent#ACTION_CREATE_SHORTCUT}. 516 * 517 * @param shortcut New shortcut to pin. If an app wants to pin an existing (either dynamic 518 * or manifest) shortcut, then it only needs to have an ID, and other fields don't have to 519 * be set, in which case, the target shortcut must be enabled. 520 * If it's a new shortcut, all the mandatory fields, such as a short label, must be 521 * set. 522 * @return The intent that should be set as the result for the calling activity, or 523 * <code>null</code> if the current launcher doesn't support shortcuts. 524 * 525 * @see Intent#ACTION_CREATE_SHORTCUT 526 * 527 * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled. 528 */ createShortcutResultIntent(@onNull ShortcutInfo shortcut)529 public Intent createShortcutResultIntent(@NonNull ShortcutInfo shortcut) { 530 try { 531 return mService.createShortcutResultIntent(mContext.getPackageName(), shortcut, 532 injectMyUserId()); 533 } catch (RemoteException e) { 534 throw e.rethrowFromSystemServer(); 535 } 536 } 537 538 /** 539 * Called internally when an app is considered to have come to the foreground 540 * even when technically it's not. This method resets the throttling for this package. 541 * For example, when the user sends an "inline reply" on a notification, the system UI will 542 * call it. 543 * 544 * @hide 545 */ onApplicationActive(@onNull String packageName, @UserIdInt int userId)546 public void onApplicationActive(@NonNull String packageName, @UserIdInt int userId) { 547 try { 548 mService.onApplicationActive(packageName, userId); 549 } catch (RemoteException e) { 550 throw e.rethrowFromSystemServer(); 551 } 552 } 553 554 /** @hide injection point */ 555 @VisibleForTesting injectMyUserId()556 protected int injectMyUserId() { 557 return mContext.getUserId(); 558 } 559 560 /** 561 * Used by framework's ShareSheet (ChooserActivity.java) to retrieve all of the direct share 562 * targets that match the given IntentFilter. 563 * 564 * @param filter IntentFilter that will be used to retrieve the matching {@link ShortcutInfo}s. 565 * @return List of {@link ShareShortcutInfo}s that match the given IntentFilter. 566 * @hide 567 */ 568 @NonNull 569 @SystemApi 570 @RequiresPermission(Manifest.permission.MANAGE_APP_PREDICTIONS) getShareTargets(@onNull IntentFilter filter)571 public List<ShareShortcutInfo> getShareTargets(@NonNull IntentFilter filter) { 572 try { 573 return mService.getShareTargets(mContext.getPackageName(), filter, 574 injectMyUserId()).getList(); 575 } catch (RemoteException e) { 576 throw e.rethrowFromSystemServer(); 577 } 578 } 579 580 /** 581 * Represents the result of a query return by {@link #getShareTargets(IntentFilter)}. 582 * 583 * @hide 584 */ 585 @SystemApi 586 public static final class ShareShortcutInfo implements Parcelable { 587 private final ShortcutInfo mShortcutInfo; 588 private final ComponentName mTargetComponent; 589 590 /** 591 * @hide 592 */ ShareShortcutInfo(@onNull ShortcutInfo shortcutInfo, @NonNull ComponentName targetComponent)593 public ShareShortcutInfo(@NonNull ShortcutInfo shortcutInfo, 594 @NonNull ComponentName targetComponent) { 595 if (shortcutInfo == null) { 596 throw new NullPointerException("shortcut info is null"); 597 } 598 if (targetComponent == null) { 599 throw new NullPointerException("target component is null"); 600 } 601 602 mShortcutInfo = shortcutInfo; 603 mTargetComponent = targetComponent; 604 } 605 ShareShortcutInfo(@onNull Parcel in)606 private ShareShortcutInfo(@NonNull Parcel in) { 607 mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader()); 608 mTargetComponent = in.readParcelable(ComponentName.class.getClassLoader()); 609 } 610 611 @NonNull getShortcutInfo()612 public ShortcutInfo getShortcutInfo() { 613 return mShortcutInfo; 614 } 615 616 @NonNull getTargetComponent()617 public ComponentName getTargetComponent() { 618 return mTargetComponent; 619 } 620 621 @Override describeContents()622 public int describeContents() { 623 return 0; 624 } 625 626 @Override writeToParcel(@onNull Parcel dest, int flags)627 public void writeToParcel(@NonNull Parcel dest, int flags) { 628 dest.writeParcelable(mShortcutInfo, flags); 629 dest.writeParcelable(mTargetComponent, flags); 630 } 631 632 public static final @NonNull Parcelable.Creator<ShareShortcutInfo> CREATOR = 633 new Parcelable.Creator<ShareShortcutInfo>() { 634 public ShareShortcutInfo createFromParcel(Parcel in) { 635 return new ShareShortcutInfo(in); 636 } 637 638 public ShareShortcutInfo[] newArray(int size) { 639 return new ShareShortcutInfo[size]; 640 } 641 }; 642 } 643 644 /** 645 * Used by framework's ShareSheet (ChooserActivity.java) to check if a given package has share 646 * target definitions in it's resources. 647 * 648 * @param packageName Package to check for share targets. 649 * @return True if the package has any share target definitions, False otherwise. 650 * @hide 651 */ 652 @SystemApi hasShareTargets(@onNull String packageName)653 public boolean hasShareTargets(@NonNull String packageName) { 654 try { 655 return mService.hasShareTargets(mContext.getPackageName(), packageName, 656 injectMyUserId()); 657 } catch (RemoteException e) { 658 throw e.rethrowFromSystemServer(); 659 } 660 } 661 } 662