diff options
| -rw-r--r-- | core/java/android/content/pm/LauncherApps.java | 72 | ||||
| -rw-r--r-- | core/java/android/content/pm/ShortcutInfo.java | 82 | ||||
| -rw-r--r-- | core/java/android/content/pm/ShortcutManager.java | 454 |
3 files changed, 338 insertions, 270 deletions
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 29b2230b4140..2eb767eddac0 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -165,15 +165,15 @@ public class LauncherApps { } /** - * Indicates that one or more shortcuts of any kinds (dynamic, pinned, or manifest) + * Indicates that one or more shortcuts of any kind (dynamic, pinned, or manifest) * have been added, updated or removed. * * <p>Only the applications that are allowed to access the shortcut information, * as defined in {@link #hasShortcutHostPermission()}, will receive it. * * @param packageName The name of the package that has the shortcuts. - * @param shortcuts all shortcuts from the package (dynamic, manifest and/or pinned) will - * be passed. Only "key" information will be provided, as defined in + * @param shortcuts All shortcuts from the package (dynamic, manifest and/or pinned). + * Only "key" information will be provided, as defined in * {@link ShortcutInfo#hasKeyFieldsOnly()}. * @param user The UserHandle of the profile that generated the change. * @@ -224,16 +224,19 @@ public class LauncherApps { public static final int FLAG_GET_ALL_KINDS = FLAG_MATCH_ALL_KINDS; /** - * Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()} for which - * fields are available. This allows quicker access to shortcut information in order to - * determine in-memory cache in the caller needs to be updated. + * Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()}'s javadoc to + * see which fields fields "key". + * This allows quicker access to shortcut information in order to + * determine whether the caller's in-memory cache needs to be updated. * - * <p>Typically, launcher applications cache all or most shortcuts' information - * in memory in order to show shortcuts without a delay. When they want to update their - * cache (e.g. when their process restart), they can fetch all shortcuts' information with - * with this flag, then check {@link ShortcutInfo#getLastChangedTimestamp()} for each - * shortcut and issue a second call to fetch the non-key information of only updated - * shortcuts. + * <p>Typically, launcher applications cache all or most shortcut information + * in memory in order to show shortcuts without a delay. + * + * When a given launcher application wants to update its cache, such as when its process + * restarts, it can fetch shortcut information with this flag. + * The application can then check {@link ShortcutInfo#getLastChangedTimestamp()} for each + * shortcut, fetching a shortcut's non-key information only if that shortcut has been + * updated. * * @see ShortcutManager */ @@ -268,8 +271,9 @@ public class LauncherApps { } /** - * If non-zero, returns only shortcuts that have been added or updated since the timestamp. - * Units are as per {@link System#currentTimeMillis()}. + * If non-zero, returns only shortcuts that have been added or updated + * since the given timestamp, expressed in milliseconds since the Epoch—see + * {@link System#currentTimeMillis()}. */ public ShortcutQuery setChangedSince(long changedSince) { mChangedSince = changedSince; @@ -304,13 +308,15 @@ public class LauncherApps { } /** - * Set query options. At least one of the {@code MATCH} flags should be set. (Otherwise - * no shortcuts will be returned.) + * Set query options. At least one of the {@code MATCH} flags should be set. Otherwise, + * no shortcuts will be returned. * - * @see {@link #FLAG_MATCH_DYNAMIC} - * @see {@link #FLAG_MATCH_PINNED} - * @see {@link #FLAG_MATCH_MANIFEST} - * @see {@link #FLAG_GET_KEY_FIELDS_ONLY} + * <ul> + * <li>{@link #FLAG_MATCH_DYNAMIC} + * <li>{@link #FLAG_MATCH_PINNED} + * <li>{@link #FLAG_MATCH_MANIFEST} + * <li>{@link #FLAG_GET_KEY_FIELDS_ONLY} + * </ul> */ public ShortcutQuery setQueryFlags(@QueryFlags int queryFlags) { mQueryFlags = queryFlags; @@ -483,8 +489,8 @@ public class LauncherApps { * the user is trying a new launcher application. The user may decide to change the default * launcher back to the calling application again, so even if a launcher application loses * this permission, it does <b>not</b> have to purge pinned shortcut information. - * Also in this situation, pinned shortcuts can still be started, even though the caller - * no longer has the shortcut host permission. + * If the calling launcher application contains pinned shortcuts, they will still work, + * even though the caller no longer has the shortcut host permission. * * @see ShortcutManager */ @@ -542,8 +548,8 @@ public class LauncherApps { * <p>This API is <b>NOT</b> cumulative; this will replace all pinned shortcuts for the package. * However, different launchers may have different set of pinned shortcuts. * - * <p>Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. + * <p>The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. * * @param packageName The target package name. * @param shortcutIds The IDs of the shortcut to be pinned. @@ -613,8 +619,8 @@ public class LauncherApps { /** * Returns the icon for this shortcut, without any badging for the profile. * - * <p>Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. + * <p>The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. * * @param density The preferred density of the icon, zero for default density. Use * density DPI values from {@link DisplayMetrics}. @@ -661,14 +667,14 @@ public class LauncherApps { /** * Returns the shortcut icon with badging appropriate for the profile. * - * <p>Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. + * <p>The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. * * @param density Optional density for the icon, or 0 to use the default density. Use * @return A badged icon for the shortcut. * * @see ShortcutManager - * @see #getShortcutBadgedIconDrawable(ShortcutInfo, int) + * @see #getShortcutIconDrawable(ShortcutInfo, int) * @see DisplayMetrics */ public Drawable getShortcutBadgedIconDrawable(ShortcutInfo shortcut, int density) { @@ -681,8 +687,8 @@ public class LauncherApps { /** * Starts a shortcut. * - * <p>Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. + * <p>The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. * * @param packageName The target shortcut package name. * @param shortcutId The target shortcut ID. @@ -703,8 +709,8 @@ public class LauncherApps { /** * Launches a shortcut. * - * <p>Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. + * <p>The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. * * @param shortcut The target shortcut. * @param sourceBounds The Rect containing the source bounds of the clicked icon. diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index 0d6a23bcdc96..ed0ac5386176 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -770,17 +770,21 @@ public final class ShortcutInfo implements Parcelable { * Sets the target activity. A shortcut will be shown along with this activity's icon * on the launcher. * - * <p>This is a mandatory field when publishing a new shortcut with + * When selecting a target activity, keep the following in mind: + * <ul> + * <li>All dynamic shortcuts must have a target activity. When a shortcut with no target + * activity is published using * {@link ShortcutManager#addDynamicShortcuts(List)} or - * {@link ShortcutManager#setDynamicShortcuts(List)}. + * {@link ShortcutManager#setDynamicShortcuts(List)}, + * the first main activity defined in the application's <code>AndroidManifest.xml</code> + * file is used. * - * <ul> - * <li>Only "main" activities (ones with an intent filter for - * {@link Intent#ACTION_MAIN} and {@link Intent#CATEGORY_LAUNCHER}) can be target + * <li>Only "main" activities—ones that define the {@link Intent#ACTION_MAIN} + * and {@link Intent#CATEGORY_LAUNCHER} intent filters—can be target * activities. * - * <li>By default, the first main activity defined in the application manifest will be - * the target. + * <li>By default, the first main activity defined in the application manifest is + * the target activity. * * <li>A target activity must belong to the publisher application. * </ul> @@ -806,8 +810,8 @@ public final class ShortcutInfo implements Parcelable { * and will be ignored. * * <p>Only icons created with {@link Icon#createWithBitmap(Bitmap)} and - * {@link Icon#createWithResource} are supported. Other types such as URI based icons - * are not supported. + * {@link Icon#createWithResource} are supported. + * Other types, such as URI-based icons, are not supported. * * @see LauncherApps#getShortcutIconDrawable(ShortcutInfo, int) * @see LauncherApps#getShortcutBadgedIconDrawable(ShortcutInfo, int) @@ -836,9 +840,9 @@ public final class ShortcutInfo implements Parcelable { * {@link ShortcutManager#addDynamicShortcuts(List)} or * {@link ShortcutManager#setDynamicShortcuts(List)}. * - * <p>This field is intended for a concise description of a shortcut. + * <p>This field is intended to be a concise description of a shortcut. * - * <p>The recommended max length is 10 characters. + * <p>The recommended maximum length is 10 characters. * * @see ShortcutInfo#getShortLabel() */ @@ -866,7 +870,7 @@ public final class ShortcutInfo implements Parcelable { * <p>This field is intended to be more descriptive than the shortcut title. The launcher * shows this instead of the short title when it has enough space. * - * <p>The recommend max length is 25 characters. + * <p>The recommend maximum length is 25 characters. * * @see ShortcutInfo#getLongLabel() */ @@ -913,7 +917,8 @@ public final class ShortcutInfo implements Parcelable { } /** - * Sets the message that should be shown when a shortcut is launched when disabled. + * Sets the message that should be shown when the user attempts to start a shortcut that + * is disabled. * * @see ShortcutInfo#getDisabledMessage() */ @@ -948,14 +953,12 @@ public final class ShortcutInfo implements Parcelable { * {@link ShortcutManager#addDynamicShortcuts(List)} or * {@link ShortcutManager#setDynamicShortcuts(List)}. * - * <p>A shortcut can launch any intent that the publisher application has a permission to - * launch -- for example, a shortcut can launch an unexported activity within the publisher - * application. - * - * <p>A shortcut intent doesn't have to point at the target activity. + * <p>A shortcut can launch any intent that the publisher application has permission to + * launch. For example, a shortcut can launch an unexported activity within the publisher + * application. A shortcut intent doesn't have to point at the target activity. * - * <p>{@code intent} can contain extras, but only values of the primitive types are - * supported so the system can persist them. + * <p>The given {@code intent} can contain extras, but these extras must contain values + * of primitive types in order for the system to persist these values. * * @see ShortcutInfo#getIntent() * @see #setIntents(Intent[]) @@ -1003,10 +1006,10 @@ public final class ShortcutInfo implements Parcelable { } /** - * Extras that application can set to any purposes. + * Extras that application can set for any purpose. * - * <p>Applications can store any meta-data of - * shortcuts in extras, and retrieve later from {@link ShortcutInfo#getExtras()}. + * <p>Applications can store arbitrary shortcut metadata in extras and retrieve the + * metadata later using {@link ShortcutInfo#getExtras()}. */ @NonNull public Builder setExtras(@NonNull PersistableBundle extras) { @@ -1026,9 +1029,9 @@ public final class ShortcutInfo implements Parcelable { /** * Returns the ID of a shortcut. * - * <p>Shortcut IDs are unique within each publisher application, and must be stable across - * devices to that shortcuts will still be valid when restored. See {@link ShortcutManager} - * for details. + * <p>Shortcut IDs are unique within each publisher application and must be stable across + * devices so that shortcuts will still be valid when restored on a different device. + * See {@link ShortcutManager} for details. */ @NonNull public String getId() { @@ -1046,8 +1049,9 @@ public final class ShortcutInfo implements Parcelable { /** * Return the target activity. * - * <p>This has nothing to do with the activity that this shortcut will launch. Launcher - * applications should show a shortcut along with the launcher icon for this activity. + * <p>This has nothing to do with the activity that this shortcut will launch. + * Launcher applications should show the launcher icon for the returned activity alongside + * this shortcut. * * @see Builder#setActivity */ @@ -1128,7 +1132,8 @@ public final class ShortcutInfo implements Parcelable { } /** - * Return the message that should be shown when a shortcut in disabled state is launched. + * Return the message that should be shown when the user attempts to start a shortcut + * that is disabled. * * @see Builder#setDisabledMessage(CharSequence) */ @@ -1143,7 +1148,7 @@ public final class ShortcutInfo implements Parcelable { } /** - * Return the categories. + * Return the shortcut's categories. * * @see Builder#setCategories(Set) */ @@ -1153,7 +1158,8 @@ public final class ShortcutInfo implements Parcelable { } /** - * Return the intent. If setIntents() was used, then return the last intent in the array. + * Returns the intent that is executed when the user selects this shortcut. + * If setIntents() was used, then return the last intent in the array. * * <p>Launcher applications <b>cannot</b> see the intent. If a {@link ShortcutInfo} is * obtained via {@link LauncherApps}, then this method will always return null. @@ -1283,7 +1289,7 @@ public final class ShortcutInfo implements Parcelable { } /** - * {@link UserHandle} on which the publisher created a shortcut. + * {@link UserHandle} on which the publisher created this shortcut. */ public UserHandle getUserHandle() { return UserHandle.of(mUserId); @@ -1333,7 +1339,7 @@ public final class ShortcutInfo implements Parcelable { } /** - * Return whether a shortcut is published AndroidManifest.xml or not. If {@code true}, + * Return whether a shortcut is published from AndroidManifest.xml or not. If {@code true}, * it's also {@link #isImmutable()}. * * <p>When an app is upgraded and a shortcut is no longer published from AndroidManifest.xml, @@ -1441,11 +1447,11 @@ public final class ShortcutInfo implements Parcelable { * <li>{@link #getUserHandle()} * </ul> * - * <p>{@link ShortcutInfo}s passed to - * {@link LauncherApps.Callback#onShortcutsChanged(String, List, UserHandle)} - * as well as returned by {@link LauncherApps#getShortcuts(ShortcutQuery, UserHandle)} with - * the {@link ShortcutQuery#FLAG_GET_KEY_FIELDS_ONLY} option will only have key information - * for performance reasons. + * <p>For performance reasons, shortcuts passed to + * {@link LauncherApps.Callback#onShortcutsChanged(String, List, UserHandle)} as well as those + * returned from {@link LauncherApps#getShortcuts(ShortcutQuery, UserHandle)} + * while using the {@link ShortcutQuery#FLAG_GET_KEY_FIELDS_ONLY} option contain only key + * information. */ public boolean hasKeyFieldsOnly() { return hasFlags(FLAG_KEY_FIELDS_ONLY); diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java index 81302714d2b6..99d578b80783 100644 --- a/core/java/android/content/pm/ShortcutManager.java +++ b/core/java/android/content/pm/ShortcutManager.java @@ -31,35 +31,40 @@ import com.android.internal.annotations.VisibleForTesting; import java.util.List; /** - * ShortcutManager manages "launcher shortcuts" (or simply "shortcuts"). Shortcuts provide users - * with quick - * ways to access activities other than the main activity from the launcher to users. For example, - * an email application may publish the "compose new email" action which will directly open the - * compose activity. The {@link ShortcutInfo} class represents shortcuts. + * The ShortcutManager manages "launcher shortcuts" (or simply "shortcuts"). Shortcuts provide + * users + * with quick access to activities other than an application's main activity in the currently-active + * launcher. For example, + * an email application may publish the "compose new email" action, which will directly open the + * compose activity. The {@link ShortcutInfo} class contains information about each of the + * shortcuts themselves. * * <h3>Dynamic Shortcuts and Manifest Shortcuts</h3> * * There are two ways to publish shortcuts: manifest shortcuts and dynamic shortcuts. * * <ul> - * <li>Manifest shortcuts are declared in a resource XML which is referred to from - * AndroidManifest.xml. Manifest shortcuts are published when an application is installed, - * and are updated when an application is upgraded with an updated XML file. - * Manifest shortcuts are immutable and their - * definitions (e.g. icons and labels) can not be changed dynamically (without upgrading the - * publisher application). - * - * <li>Dynamic shortcuts are published at runtime with {@link ShortcutManager} APIs. - * Applications can publish, update and remove dynamic shortcuts at runtime with certain limitations - * described below. + * <li>Manifest shortcuts are declared in a resource + * XML, which is referenced in the publisher application's <code>AndroidManifest.xml</code> file. + * Manifest shortcuts are published when an application is installed, + * and the details of these shortcuts change when an application is upgraded with an updated XML + * file. + * Manifest shortcuts are immutable, and their + * definitions, such as icons and labels, cannot be changed dynamically without upgrading the + * publisher application. + * + * <li>Dynamic shortcuts are published at runtime using the {@link ShortcutManager} APIs. + * Applications can publish, update, and remove dynamic shortcuts at runtime. * </ul> * - * <p>Only "main" activities (i.e. activities that handle the {@code MAIN} action and the - * {@code LAUNCHER} category) can have shortcuts. If an application has multiple main activities, - * they will have different set of shortcuts. + * <p>Only "main" activities—activities that handle the {@code MAIN} action and the + * {@code LAUNCHER} category—can have shortcuts. + * If an application has multiple main activities, these activities will have different sets + * of shortcuts. * - * <p>Dynamic shortcuts and manifest shortcuts are shown by launcher applications when the user - * takes a certain action (e.g. long-press) on an application launcher icon. + * <p>Dynamic shortcuts and manifest shortcuts are shown in the currently active launcher when + * the user long-presses on an application launcher icon. The actual gesture may be different + * depending on the launcher application. * * <p>Each launcher icon can have at most {@link #getMaxShortcutCountPerActivity()} number of * dynamic and manifest shortcuts combined. @@ -68,92 +73,79 @@ import java.util.List; * <h3>Pinning Shortcuts</h3> * * Launcher applications allow users to "pin" shortcuts so they're easier to access. Both manifest - * and dynamic shortcuts can be pinned, to avoid user's confusion. + * and dynamic shortcuts can be pinned. * Pinned shortcuts <b>cannot</b> be removed by publisher - * applications -- they are only removed when the publisher is uninstalled. (Or the user performs - * "clear data" on the publisher application on the Settings application.) + * applications; they're removed only when the user removes them, + * when the publisher application is uninstalled, or when the + * user performs the "clear data" action on the publisher application from the device's Settings + * application. * - * <p>Publisher can however "disable" pinned shortcuts so they cannot be launched. See below - * for details. + * <p>However, the publisher application can <em>disable</em> pinned shortcuts so they cannot be + * started. See the following sections for details. * * * <h3>Updating and Disabling Shortcuts</h3> * * <p>When a dynamic shortcut is pinned, even when the publisher removes it as a dynamic shortcut, - * the pinned shortcut will still be available and launchable. This allows an application to have - * more than {@link #getMaxShortcutCountPerActivity()} number of shortcuts -- for example, suppose - * {@link #getMaxShortcutCountPerActivity()} is 5: + * the pinned shortcut will still be visible and launchable. This allows an application to have + * more than {@link #getMaxShortcutCountPerActivity()} number of shortcuts. + * + * <p>For example, suppose {@link #getMaxShortcutCountPerActivity()} is 5: * <ul> * <li>A chat application publishes 5 dynamic shortcuts for the 5 most recent * conversations, "c1" - "c5". * - * <li>The user pins all of the 5 shortcuts. + * <li>The user pins all 5 of the shortcuts. * - * <li>Later, the user has 3 newer conversations ("c6", "c7" and "c8"), so the application - * re-publishes dynamic shortcuts and now it has the dynamic shortcuts "c4", "c5", "c6", "c7" - * and "c8". The publisher has to remove "c1", "c2" and "c3" because it can't have more than + * <li>Later, the user has started 3 additional conversations ("c6", "c7", and "c8"), + * so the publisher application + * re-publishes its dynamic shortcuts. The new dynamic shortcut list is: + * "c4", "c5", "c6", "c7", and "c8". + * The publisher application has to remove "c1", "c2", and "c3" because it can't have more than * 5 dynamic shortcuts. * * <li>However, even though "c1", "c2" and "c3" are no longer dynamic shortcuts, the pinned - * shortcuts for those conversations are still available and launchable. + * shortcuts for these conversations are still available and launchable. * - * <li>At this point, the application has 8 shortcuts in total, including the 3 pinned + * <li>At this point, the user can access a total of 8 shortcuts that link to activities in + * the publisher application, including the 3 pinned * shortcuts, even though it's allowed to have at most 5 dynamic shortcuts. * * <li>The application can use {@link #updateShortcuts(List)} to update any of the existing * 8 shortcuts, when, for example, the chat peers' icons have changed. * </ul> - * {@link #addDynamicShortcuts(List)} and {@link #setDynamicShortcuts(List)} can also be used - * to update existing shortcuts with the same IDs, but they <b>cannot</b> be used for - * non-dynamic pinned shortcuts because these two APIs will always try to make the passed - * shortcuts dynamic. + * The {@link #addDynamicShortcuts(List)} and {@link #setDynamicShortcuts(List)} methods + * can also be used + * to update existing shortcuts with the same IDs, but they <b>cannot</b> be used + * for updating non-dynamic, pinned shortcuts because these two methods try to convert the given + * lists of shortcuts to dynamic shortcuts. * * * <h4>Disabling Manifest Shortcuts</h4> - * Sometimes pinned shortcuts become obsolete and may not be usable. For example, a pinned shortcut - * to a group chat will be unusable when the group chat room is deleted. In cases like this, - * applications should use {@link #disableShortcuts(List)}, which will remove the specified dynamic - * shortcuts and also make the pinned shortcuts un-launchable, if any. - * {@link #disableShortcuts(List, CharSequence)} can also be used to disable shortcuts with - * a custom error message that will be shown when the user starts the shortcut. - * - * <h4>Disabling Manifest Shortcuts</h4> - * When an application is upgraded and the new version no longer has a manifest shortcut that - * the previous version had, this shortcut will no longer be published as a manifest shortcut. - * - * <p>If the shortcut is pinned, then the pinned shortcut will remain on the launcher, but will be - * disabled. Note in this case, the pinned shortcut is no longer a manifest shortcut, but is - * still <b>immutable</b> and cannot be updated with the {@link ShortcutManager} APIs. - * + * When an application is upgraded and the new version + * no longer uses a manifest shortcut that appeared in the previous version, this deprecated + * shortcut will no longer be published as a manifest shortcut. * - * <h3>Publishing Dynamic Shortcuts</h3> - * - * Applications can publish dynamic shortcuts with {@link #setDynamicShortcuts(List)} - * or {@link #addDynamicShortcuts(List)}. {@link #updateShortcuts(List)} can also be used to - * update existing (mutable) shortcuts. - * Use {@link #removeDynamicShortcuts(List)} or {@link #removeAllDynamicShortcuts()} to remove - * dynamic shortcuts. - * - * <p>Example: - * <pre> - * ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); + * <p>If the deprecated shortcut is pinned, then the pinned shortcut will remain on the launcher, + * but it will be disabled automatically. + * Note that, in this case, the pinned shortcut is no longer a manifest shortcut, but it's + * still <b>immutable</b> and cannot be updated using the {@link ShortcutManager} APIs. * - * ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "id1") - * .setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.mysite.com/"))) - * .setShortLabel("Web site") - * .setLongLabel("Open the web site") - * .setIcon(Icon.createWithResource(context, R.drawable.icon_website)) - * .build(); * - * shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut)); - * </pre> + * <h4>Disabling Dynamic Shortcuts</h4> + * Sometimes pinned shortcuts become obsolete and may not be usable. For example, a pinned shortcut + * to a group chat will be unusable when the associated group chat is deleted. In cases like this, + * applications should use {@link #disableShortcuts(List)}, which will remove the specified dynamic + * shortcuts and also make any specified pinned shortcuts un-launchable. + * The {@link #disableShortcuts(List, CharSequence)} method can also be used to disabled shortcuts + * and show users a custom error message when they attempt to launch the disabled shortcuts. * * * <h3>Publishing Manifest Shortcuts</h3> * * In order to add manifest shortcuts to your application, first add * {@code <meta-data android:name="android.app.shortcuts" />} to your main activity in - * AndroidManifest.xml. + * AndroidManifest.xml: * <pre> * <manifest xmlns:android="http://schemas.android.com/apk/res/android" * package="com.example.myapplication"> @@ -169,7 +161,8 @@ import java.util.List; * </manifest> * </pre> * - * Then define shortcuts in res/xml/shortcuts.xml. + * Then, define your application's manifest shortcuts in the <code>res/xml/shortcuts.xml</code> + * file: * <pre> * <shortcuts xmlns:android="http://schemas.android.com/apk/res/android" > * <shortcut @@ -177,7 +170,7 @@ import java.util.List; * android:enabled="true" * android:icon="@drawable/compose_icon" * android:shortcutShortLabel="@string/compose_shortcut_short_label1" - * android:shortcutLongLabel="@string/compose_shortcut_short_label1" + * android:shortcutLongLabel="@string/compose_shortcut_long_label1" * android:shortcutDisabledMessage="@string/compose_disabled_message1" * > * <intent @@ -187,114 +180,161 @@ import java.util.List; * <!-- more intents can go here; see below --> * <categories android:name="android.shortcut.conversation" /> * </shortcut> - * <!-- more shortcut can go here --> + * <!-- more shortcuts can go here --> * </shortcuts> * </pre> - * <ul> - * <li>{@code android:shortcutId} Mandatory shortcut ID * - * <li>{@code android:enabled} Default is {@code true}. Can be set to {@code false} in order - * to disable a manifest shortcut that was published on a previous version with a custom + * The following list includes descriptions for the different attributes within a manifest shortcut: + * <dl> + * <dt>android:shortcutId</dt> + * <dd>Mandatory shortcut ID</dd> + * + * <dt>android:enabled</dt> + * <dd>Default is {@code true}. Can be set to {@code false} in order + * to disable a manifest shortcut that was published in a previous version and and set a custom * disabled message. If a custom disabled message is not needed, then a manifest shortcut can - * be simply removed from the xml file rather than keeping it with {@code enabled="false"}. + * be simply removed from the XML file rather than keeping it with {@code enabled="false"}.</dd> * - * <li>{@code android:icon} Shortcut icon. + * <dt>android:icon</dt> + * <dd>Shortcut icon.</dd> * - * <li>{@code android:shortcutShortLabel} Mandatory shortcut short label. - * See {@link ShortcutInfo.Builder#setShortLabel(CharSequence)} + * <dt>android:shortcutShortLabel</dt> + * <dd>Mandatory shortcut short label. + * See {@link ShortcutInfo.Builder#setShortLabel(CharSequence)}.</dd> * - * <li>{@code android:shortcutLongLabel} Shortcut long label. - * See {@link ShortcutInfo.Builder#setLongLabel(CharSequence)} + * <dt>android:shortcutLongLabel</dt> + * <dd>Shortcut long label. + * See {@link ShortcutInfo.Builder#setLongLabel(CharSequence)}.</dd> * - * <li>{@code android:shortcutDisabledMessage} When {@code android:enabled} is set to - * {@code false}, this can be used to set a custom disabled message. + * <dt>android:shortcutDisabledMessage</dt> + * <dd>When {@code android:enabled} is set to + * {@code false}, this attribute is used to display a custom disabled message.</dd> * - * <li>{@code intent} Intent to launch. {@code android:action} is mandatory. + * <dt>intent</dt> + * <dd>Intent to launch when the user selects the shortcut. + * {@code android:action} is mandatory. * See <a href="{@docRoot}guide/topics/ui/settings.html#Intents">Using intents</a> for the - * other supported tags. Multiple intents can be provided for a single shortcut, so that - * an activity will be launched with other activities in the back stack. - * See {@link android.app.TaskStackBuilder} for details. - * </ul> + * other supported tags. + * You can provide multiple intents for a single shortcut so that an activity is launched + * with other activities in the back stack. See {@link android.app.TaskStackBuilder} for details. + * </dd> + * <dt>categories</dt> + * <dd>Specify shortcut categories. Currently only + * {@link ShortcutInfo#SHORTCUT_CATEGORY_CONVERSATION} is defined in the framework. + * </dd> + * </dl> + * + * <h3>Publishing Dynamic Shortcuts</h3> + * + * Applications can publish dynamic shortcuts with {@link #setDynamicShortcuts(List)} + * or {@link #addDynamicShortcuts(List)}. The {@link #updateShortcuts(List)} method can also be + * used to update existing, mutable shortcuts. + * Use {@link #removeDynamicShortcuts(List)} or {@link #removeAllDynamicShortcuts()} to remove + * dynamic shortcuts. + * + * <p>Example: + * <pre> + * ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); + * + * ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "id1") + * .setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.mysite.com/"))) + * .setShortLabel("Web site") + * .setLongLabel("Open the web site") + * .setIcon(Icon.createWithResource(context, R.drawable.icon_website)) + * .build(); + * + * shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut)); + * </pre> + * * * <h3>Shortcut Intents</h3> - * Dynamic shortcuts can be published with any {@link Intent#addFlags Intent flags}. Typically, - * {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} is specified possibly with other flags; otherwise, - * if the application is already running, the application is simply brought to the foreground - * and the target activity may not show up. - * - * <p>{@link ShortcutInfo.Builder#setIntents(Intent[])} can be used (instead of - * {@link ShortcutInfo.Builder#setIntent(Intent)}) with - * {@link android.app.TaskStackBuilder} in order to launch an activity with other activities - * in the back stack, so that when the user presses the back key, a "parent" activity will be shown - * instead of the user being navigated back to the launcher. - * - * <p>Manifest shortcuts can have multiple intents too to achieve the same effect. In order to - * specify multiple {@link Intent}s to a shortcut, simply list multiple <intent>s within - * a single <shortcut>. The last intent is what the user will see when a shortcut is - * launched. - * - * <p>Manifest shortcuts <b>cannot</b> have custom intent flags. The first intent of a manifest - * shortcut will always have {@link Intent#FLAG_ACTIVITY_NEW_TASK} and - * {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} set. This means, when the application is already - * running, all the existing activities will be destroyed when a manifest shortcut is launched. - * If this behavior is not desirable, one can use a "trampoline" activity (an activity - * that starts another activity in {@link Activity#onCreate} and then calls - * {@link Activity#finish()}) with {@code android:taskAffinity=""} in AndroidManifest.xml and point - * at this activity in a manifest shortcut's intent. - * - * <h3>Updating Shortcuts v.s. Re-publishing New One with Different ID</h3> - * In order to avoid users' confusion, {@link #updateShortcuts(List)} should not be used to update - * a shortcut to something that is conceptually different. + * Dynamic shortcuts can be published with any set of {@link Intent#addFlags Intent} flags. + * Typically, {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} is specified, possibly along with other + * flags; otherwise, if the application is already running, the application is simply brought to + * the foreground, and the target activity may not appear. + * + * <p>The {@link ShortcutInfo.Builder#setIntents(Intent[])} method can be used instead of + * {@link ShortcutInfo.Builder#setIntent(Intent)} with {@link android.app.TaskStackBuilder} + * in order to launch an activity with other activities in the back stack. + * When the user selects a shortcut to load an activity with a back stack, + * then presses the back key, a "parent" activity will be shown instead of the user being + * navigated back to the launcher. + * + * <p>Manifest shortcuts can also have multiple intents to achieve the same effect. + * In order to associate multiple {@link Intent} objects with a shortcut, simply list multiple + * <code><intent></code> elements within a single <code><shortcut></code> element. + * The last intent specifies what the user will see when they launch a shortcut. + * + * <p>Manifest shortcuts <b>cannot</b> have custom intent flags. + * The first intent of a manifest shortcut will always have {@link Intent#FLAG_ACTIVITY_NEW_TASK} + * and {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} set. + * This means, when the application is already running, all the existing activities will be + * destroyed when a manifest shortcut is launched. + * If this behavior is not desirable, you can use a <em>trampoline activity</em>, + * or an invisible activity that starts another activity in {@link Activity#onCreate}, + * then calls {@link Activity#finish()}. + * The first activity should include an attribute setting + * of {@code android:taskAffinity=""} in the application's <code>AndroidManifest.xml</code> + * file, and the intent within the manifest shortcut should point at this first activity. + * + * + * <h3>Showing New Information in a Shortcut</h3> + * In order to avoid confusion, you should not use {@link #updateShortcuts(List)} to update + * a shortcut so that it contains conceptually different information. * * <p>For example, a phone application may publish the most frequently called contact as a dynamic - * shortcut. Over the time, this contact may change, but when it changes the application should - * publish a new contact with a different ID with either + * shortcut. Over time, this contact may change; when it does, the application should + * represent the changed contact with a new shortcut that contains a different ID, using either * {@link #setDynamicShortcuts(List)} or {@link #addDynamicShortcuts(List)}, rather than updating * the existing shortcut with {@link #updateShortcuts(List)}. + * This is because when the shortcut is pinned, changing + * it to reference a different contact will likely confuse the user. * - * This is because when the shortcut is pinned, changing it to a different contact - * will likely confuse the user. - * - * <p>On the other hand, when the contact's information (e.g. the name or picture) has changed, - * then the application should use {@link #updateShortcuts(List)} so that the pinned shortcut - * will be updated too. + * <p>On the other hand, when the + * contact's information has changed, such as the name or picture, the application should + * use {@link #updateShortcuts(List)} so that the pinned shortcut is updated too. * * * <h3>Shortcut Display Order</h3> - * When the launcher show the shortcuts for a launcher icon, the showing order should be the - * following: + * When the launcher displays the shortcuts that are associated with a particular launcher icon, + * the shortcuts should appear in the following order: * <ul> * <li>First show manifest shortcuts - * ({@link ShortcutInfo#isDeclaredInManifest()} is {@code true}), - * and then dynamic shortcuts ({@link ShortcutInfo#isDynamic()} is {@code true}). - * <li>Within each category, sort by {@link ShortcutInfo#getRank()}. + * (if {@link ShortcutInfo#isDeclaredInManifest()} is {@code true}), + * and then show dynamic shortcuts (if {@link ShortcutInfo#isDynamic()} is {@code true}). + * <li>Within each category of shortcuts (manifest and dynamic), sort the shortcuts in order + * of increasing rank according to {@link ShortcutInfo#getRank()}. * </ul> - * <p>Shortcut ranks are non-negative sequential integers for each target activity. Ranks of - * existing shortcuts can be updated with - * {@link #updateShortcuts(List)} ({@link #addDynamicShortcuts(List)} and - * {@link #setDynamicShortcuts(List)} may be used too). - * - * <p>Ranks will be auto-adjusted so that they're unique for each target activity for each category + * <p>Shortcut ranks are non-negative sequential integers + * that determine the order in which shortcuts appear, assuming that the shortcuts are all in + * the same category. + * Ranks of existing shortcuts can be updated with + * {@link #updateShortcuts(List)}; you can use {@link #addDynamicShortcuts(List)} and + * {@link #setDynamicShortcuts(List)}, too. + * + * <p>Ranks are auto-adjusted so that they're unique for each target activity in each category * (dynamic or manifest). For example, if there are 3 dynamic shortcuts with ranks 0, 1 and 2, - * adding another dynamic shortcut with rank = 1 means to place this shortcut at the second - * position. The third and forth shortcuts (that were originally second and third) will be adjusted - * to 2 and 3 respectively. + * adding another dynamic shortcut with a rank of 1 represents a request to place this shortcut at + * the second position. + * In response, the third and fourth shortcuts move closer to the bottom of the shortcut list, + * with their ranks changing to 2 and 3, respectively. * * <h3>Rate Limiting</h3> * - * Calls to {@link #setDynamicShortcuts(List)}, {@link #addDynamicShortcuts(List)} and - * {@link #updateShortcuts(List)} may be rate-limited when called by background applications (i.e. - * applications with no foreground activity or service). When rate-limited, these APIs will return - * {@code false}. + * Calls to {@link #setDynamicShortcuts(List)}, {@link #addDynamicShortcuts(List)}, and + * {@link #updateShortcuts(List)} may be rate-limited when called by background applications, or + * applications with no foreground activity or service. When you attempt to call these methods + * from a background application after exceeding the rate limit, these APIs return {@code false}. * - * <p>Applications with a foreground activity or service will not be rate-limited. + * <p>Applications with a foreground activity or service are not rate-limited. * * <p>Rate-limiting will be reset upon certain events, so that even background applications - * will be able to call these APIs again (until they are rate-limited again). + * can call these APIs again until they are rate limit is reached again. + * These events include the following: * <ul> - * <li>When an application comes to foreground. + * <li>When an application comes to the foreground. * <li>When the system locale changes. - * <li>When the user performs "inline reply" on a notification. + * <li>When the user performs an "inline reply" action on a notification. * </ul> * * <p>When rate-limiting is active, {@link #isRateLimitingActive()} returns {@code true}. @@ -302,43 +342,46 @@ import java.util.List; * <h4>Resetting rate-limiting for testing</h4> * * If your application is rate-limited during development or testing, you can use the - * "Reset ShortcutManager rate-limiting" development option, or the following adb command to reset - * it. + * "Reset ShortcutManager rate-limiting" development option or the following adb command to reset + * it: * <pre> * adb shell cmd shortcut reset-throttling [ --user USER-ID ] * </pre> * - * <h3>Handling System Locale Change</h3> + * <h3>Handling System Locale Changes</h3> * * Applications should update dynamic and pinned shortcuts when the system locale changes * using the {@link Intent#ACTION_LOCALE_CHANGED} broadcast. * - * <p>When the system locale changes, rate-limiting will be reset, so even background applications - * what were previously rate-limited will be able to call {@link #updateShortcuts(List)}. + * <p>When the system locale changes, rate-limiting is reset, so even background applications + * can set dynamic shortcuts, add dynamic shortcuts, and update shortcuts until the rate limit + * is reached again. * * * <h3>Backup and Restore</h3> * - * When an application has {@code android:allowBackup="true"} in its AndroidManifest.xml, pinned - * shortcuts will be backed up automatically and restored when the user sets up a new device. + * When an application has the {@code android:allowBackup="true"} attribute assignment included + * in its <code>AndroidManifest.xml</code> file, pinned shortcuts are + * backed up automatically and are restored when the user sets up a new device. * - * <h4>What will be backed up and what will not be backed up</h4> + * <h4>Categories of Shortcuts that are Backed Up</h4> * * <ul> - * <li>Pinned shortcuts will be backed up. Bitmap icons will not be backed up by the system, - * but launcher applications should back them up and restore them, so the user will still get - * icons for pinned shortcuts on the launcher. Applications can always use + * <li>Pinned shortcuts are backed up. Bitmap icons are not backed up by the system, + * but launcher applications should back them up and restore them so that the user still sees icons + * for pinned shortcuts on the launcher. Applications can always use * {@link #updateShortcuts(List)} to re-publish icons. * - * <li>Manifest shortcuts will not be backed up, but when an application is re-installed on a new - * device, they will be re-published from AndroidManifest.xml anyway. + * <li>Manifest shortcuts are not backed up, but when an application is re-installed on a new + * device, they are re-published from the <code>AndroidManifest.xml</code> file, anyway. * - * <li>Dynamic shortcuts will <b>not</b> be backed up. + * <li>Dynamic shortcuts are <b>not</b> backed up. * </ul> * - * <p>Because dynamic shortcuts will not restored, it is recommended that applications check - * currently published dynamic shortcuts with {@link #getDynamicShortcuts()} when they start, - * and re-publish dynamic shortcuts when necessary. + * <p>Because dynamic shortcuts are not restored, it is recommended that applications check + * currently-published dynamic shortcuts using {@link #getDynamicShortcuts()} + * each time they are launched, and they should re-publish + * dynamic shortcuts when necessary. * * <pre> * public class MainActivity extends Activity { @@ -351,7 +394,7 @@ import java.util.List; * // Application restored; re-publish dynamic shortcuts. * * if (shortcutManager.getPinnedShortcuts().size() > 0) { - * // Pinned shortcuts have been restored. use updateShortcuts() to make sure + * // Pinned shortcuts have been restored. Use updateShortcuts() to make sure * // they have up-to-date information. * } * } @@ -364,30 +407,33 @@ import java.util.List; * * <h4>Backup/restore and shortcut IDs</h4> * - * Because pinned shortcuts will be backed up and restored on new devices, shortcut IDs should be - * meaningful across devices; that is, IDs should be either stable constant strings, or server-side - * identifiers, rather than identifiers generated locally that may not make sense on other devices. + * Because pinned shortcuts are backed up and restored on new devices, shortcut IDs should be + * meaningful across devices; that is, IDs should contain either stable, constant strings + * or server-side identifiers, + * rather than identifiers generated locally that might not make sense on other devices. * * * <h3>Report Shortcut Usage and Prediction</h3> * - * Launcher applications may be capable of predicting which shortcuts will most likely be used at - * the moment with the shortcut usage history data. + * Launcher applications may be capable of predicting which shortcuts will most likely be + * used at a given time by examining the shortcut usage history data. * - * <p>In order to provide launchers with such data, publisher applications should report which - * shortcut is used with {@link #reportShortcutUsed(String)} when a shortcut is started, + * <p>In order to provide launchers with such data, publisher applications should + * report the shortcuts that are used with {@link #reportShortcutUsed(String)} + * when a shortcut is selected, * <b>or when an action equivalent to a shortcut is taken by the user even if it wasn't started * with the shortcut</b>. * - * <p>For example, suppose a GPS navigation application exposes "navigate to work" as a shortcut. - * Then it should report it when the user starts this shortcut, and also when the user navigates - * to work within the application without using the shortcut. This helps the launcher application - * learn that the user wants to navigate to work at a certain time every weekday, so that the - * launcher can show this shortcut in a suggestion list. + * <p>For example, suppose a GPS navigation application supports "navigate to work" as a shortcut. + * It should then report when the user selects this shortcut <b>and</b> when the user chooses + * to navigate to work within the application itself. + * This helps the launcher application + * learn that the user wants to navigate to work at a certain time every + * weekday, and it can then show this shortcut in a suggestion list at the right time. * * <h3>Launcher API</h3> * - * {@link LauncherApps} provides APIs for launcher applications to access shortcuts. + * The {@link LauncherApps} class provides APIs for launcher applications to access shortcuts. */ public class ShortcutManager { private static final String TAG = "ShortcutManager"; @@ -413,16 +459,16 @@ public class ShortcutManager { } /** - * Publish a list of shortcuts. All existing dynamic shortcuts from the caller application - * will be replaced. If there's already pinned shortcuts with the same IDs, they will all be - * updated, unless they're immutable. + * Publish the list of shortcuts. All existing dynamic shortcuts from the caller application + * will be replaced. If there are already pinned shortcuts with the same IDs, + * the mutable pinned shortcuts are updated. * * <p>This API will be rate-limited. * * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited. * * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded, - * or trying to update immutable shortcuts. + * or when trying to update immutable shortcuts. */ public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) { try { @@ -460,15 +506,15 @@ public class ShortcutManager { } /** - * Publish list of dynamic shortcuts. If there's already dynamic or pinned shortcuts with - * the same IDs, they will all be updated, unless they're immutable. + * Publish the list of dynamic shortcuts. If there are already dynamic or pinned shortcuts with + * the same IDs, each mutable shortcut is updated. * * <p>This API will be rate-limited. * * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited. * * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded, - * or trying to update immutable shortcuts. + * or when trying to update immutable shortcuts. */ public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) { try { @@ -517,13 +563,13 @@ public class ShortcutManager { /** * Update all existing shortcuts with the same IDs. Target shortcuts may be pinned and/or - * dynamic, but may not be immutable. + * dynamic, but they must not be immutable. * * <p>This API will be rate-limited. * * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited. * - * @throws IllegalArgumentException if trying to update immutable shortcuts. + * @throws IllegalArgumentException If trying to update immutable shortcuts. */ public boolean updateShortcuts(List<ShortcutInfo> shortcutInfoList) { try { @@ -535,7 +581,10 @@ public class ShortcutManager { } /** - * Disable pinned shortcuts. See {@link ShortcutManager}'s class javadoc for details. + * Disable pinned shortcuts. For more details, see the Javadoc for the {@link ShortcutManager} + * class. + * + * @throws IllegalArgumentException If trying to disable immutable shortcuts. */ public void disableShortcuts(@NonNull List<String> shortcutIds) { try { @@ -568,8 +617,11 @@ public class ShortcutManager { } /** - * Disable pinned shortcuts with a custom error message. - * See {@link ShortcutManager}'s class javadoc for details. + * Disable pinned shortcuts, showing the user a custom error message when they try to select + * the disabled shortcuts. + * For more details, see the Javadoc for the {@link ShortcutManager} class. + * + * @throws IllegalArgumentException If trying to disable immutable shortcuts. */ public void disableShortcuts(@NonNull List<String> shortcutIds, CharSequence disabledMessage) { try { @@ -582,7 +634,10 @@ public class ShortcutManager { } /** - * Re-enable disabled pinned shortcuts. + * Re-enable pinned shortcuts that were previously disabled. If the target shortcuts + * already enabled, this method does nothing. + * + * @throws IllegalArgumentException If trying to enable immutable shortcuts. */ public void enableShortcuts(@NonNull List<String> shortcutIds) { try { @@ -601,7 +656,7 @@ public class ShortcutManager { } /** - * Return the max number of dynamic and manifest shortcuts that each launcher icon + * Return the maximum number of dynamic and manifest shortcuts that each launcher icon * can have at a time. */ public int getMaxShortcutCountPerActivity() { @@ -684,9 +739,10 @@ public class ShortcutManager { } /** - * Applications that publish shortcuts should call this method whenever a shortcut is started - * or an action equivalent to a shortcut is taken. See the {@link ShortcutManager} class - * javadoc for details. + * Applications that publish shortcuts should call this method + * whenever the user selects the shortcut containing the given ID or when the user completes + * an action in the application that is equivalent to selecting the shortcut. + * For more details, see the Javadoc for the {@link ShortcutManager} class * * <p>The information is accessible via {@link UsageStatsManager#queryEvents} * Typically, launcher applications use this information to build a prediction model |