diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 528fe20023915..2133222c7f544 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -164,17 +164,19 @@ public class LauncherApps { } /** - * Indicates that one or more shortcuts (which may be dynamic and/or pinned) + * Indicates that one or more shortcuts of any kinds (dynamic, pinned, or manifest) * have been added, updated or removed. * *
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).
- * Only "key" information will be provided, as defined in
+ * @param shortcuts all shortcuts from the package (dynamic, manifest and/or pinned) will
+ * be passed. Only "key" information will be provided, as defined in
* {@link ShortcutInfo#hasKeyFieldsOnly()}.
* @param user The UserHandle of the profile that generated the change.
+ *
+ * @see ShortcutManager
*/
public void onShortcutsChanged(@NonNull String packageName,
@NonNull List 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.
+ *
+ * @see ShortcutManager
*/
public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;
@@ -255,8 +267,8 @@ public class LauncherApps {
}
/**
- * If non-zero, returns only shortcuts that have been added or updated since the timestamp,
- * which is a milliseconds since the Epoch.
+ * If non-zero, returns only shortcuts that have been added or updated since the timestamp.
+ * Units are as per {@link System#currentTimeMillis()}.
*/
public ShortcutQuery setChangedSince(long changedSince) {
mChangedSince = changedSince;
@@ -273,7 +285,7 @@ public class LauncherApps {
/**
* If non-null, return only the specified shortcuts by ID. When setting this field,
- * a packange name must also be set with {@link #setPackage}.
+ * a package name must also be set with {@link #setPackage}.
*/
public ShortcutQuery setShortcutIds(@Nullable List Only the default launcher can access the shortcut information.
*
- * Note when this method returns {@code false}, that may be a temporary situation because
+ * Note when this method returns {@code false}, it may be a temporary situation because
* the user is trying a new launcher application. The user may decide to change the default
- * launcher to the calling application again, so even if a launcher application loses
+ * launcher back to the calling application again, so even if a launcher application loses
* this permission, it does not 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.
+ *
+ * @see ShortcutManager
*/
public boolean hasShortcutHostPermission() {
try {
@@ -474,7 +496,7 @@ public class LauncherApps {
}
/**
- * Returns the IDs of {@link ShortcutInfo}s that match {@code query}.
+ * Returns {@link ShortcutInfo}s that match {@code query}.
*
* Callers must be allowed to access the shortcut information, as defined in {@link
* #hasShortcutHostPermission()}.
@@ -483,6 +505,8 @@ public class LauncherApps {
* @param user The UserHandle of the profile.
*
* @return the IDs of {@link ShortcutInfo}s that match the query.
+ *
+ * @see ShortcutManager
*/
@Nullable
public List Callers 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}.
+ *
+ * @return The drawable associated with the shortcut.
+ *
+ * @see ShortcutManager
* @see #getShortcutBadgedIconDrawable(ShortcutInfo, int)
* @see DisplayMetrics
- * @return The drawable associated with the shortcut.
*/
public Drawable getShortcutIconDrawable(@NonNull ShortcutInfo shortcut, int density) {
if (shortcut.hasIconFile()) {
@@ -628,10 +660,15 @@ public class LauncherApps {
/**
* Returns the shortcut icon with badging appropriate for the profile.
*
+ * Callers 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
- * {@link DisplayMetrics} for DPI values.
- * @see DisplayMetrics
* @return A badged icon for the shortcut.
+ *
+ * @see ShortcutManager
+ * @see #getShortcutBadgedIconDrawable(ShortcutInfo, int)
+ * @see DisplayMetrics
*/
public Drawable getShortcutBadgedIconDrawable(ShortcutInfo shortcut, int density) {
final Drawable originalIcon = getShortcutIconDrawable(shortcut, density);
@@ -641,7 +678,7 @@ public class LauncherApps {
}
/**
- * Launches a shortcut.
+ * Starts a shortcut.
*
* Callers must be allowed to access the shortcut information, as defined in {@link
* #hasShortcutHostPermission()}.
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 39e15e01bab4c..8ea77d6428a8a 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -22,8 +22,10 @@ import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
+import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcel;
@@ -42,20 +44,10 @@ import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Set;
-// TODO Enhance javadoc
/**
+ * Represents a "launcher shortcut" that can be published via {@link ShortcutManager}.
*
- * Represents a shortcut from an application.
- *
- * Notes about icons:
- * Only "main" activities -- i.e. ones with an intent filter for
- * {@link Intent#ACTION_MAIN} and {@link Intent#CATEGORY_LAUNCHER} can be target activities.
+ * This is a mandatory field when publishing a new shortcut with
+ * {@link ShortcutManager#addDynamicShortcuts(List)} or
+ * {@link ShortcutManager#setDynamicShortcuts(List)}.
*
- * By default, the first main activity defined in the application manifest will be
+ * The package name of the target activity must match the package name of the shortcut
- * publisher.
+ * This has nothing to do with the activity that this shortcut will launch. This is
- * a hint to the launcher app about which launcher icon to associate this shortcut with.
+ * @see ShortcutInfo#getActivity()
*/
@NonNull
public Builder setActivity(@NonNull ComponentName activity) {
@@ -748,18 +748,23 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Sets an icon.
+ * Sets an icon of a shortcut.
*
- * For performance and security reasons, icons will NOT be available on instances
- * returned by {@link ShortcutManager} or {@link LauncherApps}. Default launcher application
- * can use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}
+ * Icons are not available on {@link ShortcutInfo} instances
+ * returned by {@link ShortcutManager} or {@link LauncherApps}. The default launcher
+ * application can use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}
* or {@link LauncherApps#getShortcutBadgedIconDrawable(ShortcutInfo, int)} to fetch
* shortcut icons.
+ *
+ * Tints set with {@link Icon#setTint} or {@link Icon#setTintList} are not supported
+ * and will be ignored.
+ *
+ * Only icons created with {@link Icon#createWithBitmap(Bitmap)} and
+ * {@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)
*/
@NonNull
public Builder setIcon(Icon icon) {
@@ -781,11 +786,15 @@ public final class ShortcutInfo implements Parcelable {
/**
* Sets the short title of a shortcut.
*
- * This is a mandatory field, unless it's passed to
- * {@link ShortcutManager#updateShortcuts(List)}.
+ * This is a mandatory field when publishing a new shortcut with
+ * {@link ShortcutManager#addDynamicShortcuts(List)} or
+ * {@link ShortcutManager#setDynamicShortcuts(List)}.
*
- * This field is intended for a concise description of a shortcut displayed under
- * an icon. The recommend max length is 10 characters.
+ * This field is intended for a concise description of a shortcut.
+ *
+ * The recommended max length is 10 characters.
+ *
+ * @see ShortcutInfo#getShortLabel()
*/
@NonNull
public Builder setShortLabel(@NonNull CharSequence shortLabel) {
@@ -809,8 +818,11 @@ public final class ShortcutInfo implements Parcelable {
* Sets the text of a shortcut.
*
* 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.
- * The recommend max length is 25 characters.
+ * shows this instead of the short title when it has enough space.
+ *
+ * The recommend max length is 25 characters.
+ *
+ * @see ShortcutInfo#getLongLabel()
*/
@NonNull
public Builder setLongLabel(@NonNull CharSequence longLabel) {
@@ -854,6 +866,11 @@ public final class ShortcutInfo implements Parcelable {
return this;
}
+ /**
+ * Sets the message that should be shown when a shortcut is launched when disabled.
+ *
+ * @see ShortcutInfo#getDisabledMessage()
+ */
@NonNull
public Builder setDisabledMessage(@NonNull CharSequence disabledMessage) {
Preconditions.checkState(
@@ -869,6 +886,7 @@ public final class ShortcutInfo implements Parcelable {
* categorise shortcuts.
*
* @see #SHORTCUT_CATEGORY_CONVERSATION
+ * @see ShortcutInfo#getCategories()
*/
@NonNull
public Builder setCategories(Set This is a mandatory field when publishing a new shortcut with
+ * {@link ShortcutManager#addDynamicShortcuts(List)} or
+ * {@link ShortcutManager#setDynamicShortcuts(List)}.
+ *
+ * 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.
+ *
+ * A shortcut intent doesn't have to point at the target activity.
+ *
+ * {@code intent} can contain extras, but only values of the primitive types are
+ * supported so the system can persist them.
+ *
+ * @see ShortcutInfo#getIntent()
*/
@NonNull
public Builder setIntent(@NonNull Intent intent) {
@@ -890,6 +922,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* "Rank" of a shortcut, which is a non-negative value that's used by the launcher app
* to sort shortcuts.
+ *
+ * See {@link ShortcutInfo#getRank()} for details.
*/
@NonNull
public Builder setRank(int rank) {
@@ -903,7 +937,7 @@ public final class ShortcutInfo implements Parcelable {
* Extras that application can set to any purposes.
*
* Applications can store any meta-data of
- * shortcuts in this, and retrieve later from {@link ShortcutInfo#getExtras()}.
+ * shortcuts in extras, and retrieve later from {@link ShortcutInfo#getExtras()}.
*/
@NonNull
public Builder setExtras(@NonNull PersistableBundle extras) {
@@ -921,7 +955,11 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the ID of the shortcut.
+ * Returns the ID of a shortcut.
+ *
+ * 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.
*/
@NonNull
public String getId() {
@@ -929,7 +967,7 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the package name of the creator application.
+ * Return the package name of the publisher application.
*/
@NonNull
public String getPackage() {
@@ -937,11 +975,10 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the target activity, which may be null, in which case the shortcut is not associated
- * with a specific activity.
+ * Return the target activity.
*
- * This has nothing to do with the activity that this shortcut will launch. This is
- * a hint to the launcher app that on which launcher icon this shortcut should be shown.
+ * 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.
*
* @see Builder#setActivity
*/
@@ -956,11 +993,7 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Icon.
- *
- * For performance reasons, this will NOT be available when an instance is returned
- * by {@link ShortcutManager} or {@link LauncherApps}. A launcher application needs to use
- * other APIs in LauncherApps to fetch the bitmap.
+ * Returns the shortcut icon.
*
* @hide
*/
@@ -996,10 +1029,9 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the shorter version of the shortcut title.
+ * Return the shorter description of a shortcut.
*
- * All shortcuts must have a non-empty title, but this method will return null when
- * {@link #hasKeyFieldsOnly()} is true.
+ * @see Builder#setShortLabel(CharSequence)
*/
@Nullable
public CharSequence getShortLabel() {
@@ -1012,7 +1044,9 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the shortcut text.
+ * Return the longer description of a shortcut.
+ *
+ * @see Builder#setLongLabel(CharSequence)
*/
@Nullable
public CharSequence getLongLabel() {
@@ -1026,6 +1060,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* Return the message that should be shown when a shortcut in disabled state is launched.
+ *
+ * @see Builder#setDisabledMessage(CharSequence)
*/
@Nullable
public CharSequence getDisabledMessage() {
@@ -1039,6 +1075,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* Return the categories.
+ *
+ * @see Builder#setCategories(Set)
*/
@Nullable
public Set All shortcuts must have an intent, but this method will return null when
- * {@link #hasKeyFieldsOnly()} is true.
+ * Launcher applications cannot see the intent. If a {@link ShortcutInfo} is
+ * obtained via {@link LauncherApps}, then this method will always return null.
+ * Launchers can only start a shortcut intent with {@link LauncherApps#startShortcut}.
*
- * Launcher apps cannot see the intent. If a {@link ShortcutInfo} is obtained via
- * {@link LauncherApps}, then this method will always return null. Launcher apps can only
- * start a shortcut intent with {@link LauncherApps#startShortcut}.
+ * @see Builder#setIntent(Intent)
*/
@Nullable
public Intent getIntent() {
@@ -1096,6 +1133,10 @@ public final class ShortcutInfo implements Parcelable {
*
* "Floating" shortcuts (i.e. shortcuts that are neither dynamic nor manifest) will all
* have rank 0, because there's no sorting for them.
+ *
+ * See the {@link ShortcutManager}'s class javadoc for details.
+ *
+ * @see Builder#setRank(int)
*/
public int getRank() {
return mRank;
@@ -1139,6 +1180,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* Extras that application can set to any purposes.
+ *
+ * @see Builder#setExtras(PersistableBundle)
*/
@Nullable
public PersistableBundle getExtras() {
@@ -1151,7 +1194,7 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * {@link UserHandle} on which the publisher created shortcuts.
+ * {@link UserHandle} on which the publisher created a shortcut.
*/
public UserHandle getUserHandle() {
return UserHandle.of(mUserId);
@@ -1201,16 +1244,13 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return whether a shortcut is published via AndroidManifest.xml or not. If {@code true},
+ * Return whether a shortcut is published AndroidManifest.xml or not. If {@code true},
* it's also {@link #isImmutable()}.
*
* When an app is upgraded and a shortcut is no longer published from AndroidManifest.xml,
* this will be set to {@code false}. If the shortcut is not pinned, then it'll just disappear.
* However, if it's pinned, it will still be alive, and {@link #isEnabled()} will be
* {@code false} and {@link #isImmutable()} will be {@code true}.
- *
- * NOTE this is whether a shortcut is published from the current version's
- * AndroidManifest.xml.
*/
public boolean isDeclaredInManifest() {
return hasFlags(FLAG_MANIFEST);
@@ -1311,6 +1351,12 @@ public final class ShortcutInfo implements Parcelable {
* {@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.
*/
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 1af63a01ce2bc..f6c0be07db84a 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -20,6 +20,7 @@ import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.app.usage.UsageStatsManager;
import android.content.Context;
+import android.content.Intent;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -28,62 +29,333 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
-// TODO Enhance javadoc
/**
- * TODO: Update to reflect DR changes, such as manifest shortcuts. The shortcuts that are currently published by the above APIs are called "dynamic", because
- * they can be removed by the creator application at any time. The user may "pin" dynamic shortcuts
- * on Launcher to make "pinned" shortcuts. Pinned shortcuts cannot be removed by the creator
- * app. An application can obtain all pinned shortcuts from itself with
- * {@link #getPinnedShortcuts()}. Applications should keep the pinned shortcut information
- * up-to-date using {@link #updateShortcuts(List)}.
+ * The number of pinned shortcuts does not affect the number of dynamic shortcuts that can be
- * published by an application at a time.
- * No matter how many pinned shortcuts that Launcher has for an application, the
- * application can still always publish {@link #getMaxShortcutCountPerActivity()} number of
- * dynamic
- * shortcuts.
+ * 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.
*
- * 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.
*
- * Each shortcut must have an ID, which must be unique within each application. When a shortcut is
- * published, existing shortcuts with the same ID will be updated. Note this may include a
- * pinned shortcut.
+ * Each launcher icon can have at most {@link #getMaxShortcutCountPerActivity()} number of
+ * dynamic and manifest shortcuts combined.
+ *
+ *
+ * Publisher can however "disable" pinned shortcuts so they cannot be launched. See below
+ * for details.
+ *
+ *
+ * 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:
+ * 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 immutable and cannot be updated with the {@link ShortcutManager} APIs.
+ *
+ *
+ * Example:
+ * 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
+ * {@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 a different contact
+ * will likely confuse the user.
+ *
+ * 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.
+ *
+ *
+ * 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).
+ *
+ * Ranks will be auto-adjusted so that they're unique for each target activity for 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.
+ *
+ * Applications with a foreground activity or service will not be rate-limited.
+ *
+ * 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).
+ * 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)}.
*
*
* Note that:
* 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.
*
- * 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,
+ * or when an action equivalent to a shortcut is taken by the user even if it wasn't started
+ * with the shortcut.
+ *
+ * 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.
+ *
+ * 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 {@code shortcutInfoList} contains more than
- * {@link #getMaxShortcutCountPerActivity()} shortcuts.
+ * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
+ * or trying to update immutable shortcuts.
*/
public boolean setDynamicShortcuts(@NonNull List 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 the caller application has already published the
- * max number of dynamic shortcuts.
+ * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
+ * or trying to update immutable shortcuts.
*/
public boolean addDynamicShortcuts(@NonNull List 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.
*/
public boolean updateShortcuts(List The information is accessible via {@link UsageStatsManager#queryEvents}
* Typically, launcher applications use this information to build a prediction model
- *
- *
- * @see {@link ShortcutManager}.
+ * @see ShortcutManager
*/
public final class ShortcutInfo implements Parcelable {
static final String TAG = "Shortcut";
@@ -149,7 +141,7 @@ public final class ShortcutInfo implements Parcelable {
public @interface CloneFlags {}
/**
- * Shortcut category for
+ * Shortcut category for messaging related actions, such as chat.
*/
public static final String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
@@ -665,6 +657,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* Builder class for {@link ShortcutInfo} objects.
+ *
+ * @see ShortcutManager
*/
public static class Builder {
private final Context mContext;
@@ -727,19 +721,25 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Sets the target activity. A shortcut will be shown with this activity on the launcher.
+ * Sets the target activity. A shortcut will be shown along with this activity's icon
+ * on the launcher.
*
- *
+ *
*
- *
- *
- *
- *
+ * ShortcutManager manages "launcher shortcuts" (or simply "shortcuts"). Shortcuts provide user
+ * 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.
*
- * {@link ShortcutManager} manages shortcuts created by applications.
+ * Dynamic Shortcuts and Manifest Shortcuts
*
- * Dynamic shortcuts and pinned shortcuts
+ * There are two ways to publish shortcuts: manifest shortcuts and dynamic shortcuts.
*
- * An application can publish shortcuts with {@link #setDynamicShortcuts(List)} and
- * {@link #addDynamicShortcuts(List)}. There can be at most
- * {@link #getMaxShortcutCountPerActivity()} number of dynamic shortcuts at a time from the
- * same application.
- * A dynamic shortcut can be deleted with {@link #removeDynamicShortcuts(List)}, and apps
- * can also use {@link #removeAllDynamicShortcuts()} to delete all dynamic shortcuts.
+ *
+ *
*
- * Shortcut IDs
+ * Pinning Shortcuts
+ *
+ * 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.
+ * Pinned shortcuts cannot 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.)
+ *
+ * Updating and Disabling Shortcuts
+ *
+ *
+ *
+ * {@link #addDynamicShortcuts(List)} and {@link #setDynamicShortcuts(List)} can also be used
+ * to update existing shortcuts with the same IDs, but they cannot be used for
+ * non-dynamic pinned shortcuts because these two APIs will always try to make the passed
+ * shortcuts dynamic.
+ *
+ *
+ * Disabling Manifest Shortcuts
+ * 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.
+ *
+ * Disabling Manifest Shortcuts
+ * 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.
+ *
+ * Publishing Dynamic Shortcuts
+ *
+ * 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.
+ *
+ *
+ * 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));
+ *
+ *
+ *
+ * Publishing Manifest Shortcuts
+ *
+ * In order to add manifest shortcuts to your application, first add
+ * {@code
+ * <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ * package="com.example.myapplication">
+ * <application . . .>
+ * <activity android:name="Main">
+ * <intent-filter>
+ * <action android:name="android.intent.action.MAIN" />
+ * <category android:name="android.intent.category.LAUNCHER" />
+ * </intent-filter>
+ * <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/>
+ * </activity>
+ * </application>
+ * </manifest>
+ *
+ *
+ * Then define shortcuts in res/xml/shortcuts.xml.
+ *
+ * <shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ * <shortcut
+ * android:shortcutId="compose"
+ * android:enabled="true"
+ * android:icon="@drawable/compose_icon"
+ * android:shortcutShortLabel="@string/compose_shortcut_short_label1"
+ * android:shortcutLongLabel="@string/compose_shortcut_short_label1"
+ * android:shortcutDisabledMessage="@string/compose_disabled_message1"
+ * >
+ * <intent
+ * android:action="android.intent.action.VIEW"
+ * android:targetPackage="com.example.myapplication"
+ * android:targetClass="com.example.myapplication.ComposeActivity" />
+ * <categories android:name="android.shortcut.conversation" />
+ * </shortcut>
+ * <!-- more shortcut can go here -->
+ * </shortcuts>
+ *
+ *
+ *
+ *
+ * Updating Shortcuts v.s. Re-publishing New One with Different ID
+ * In order to avoid users' confusion, {@link #updateShortcuts(List)} should not be used to update
+ * a shortcut to something that is conceptually different.
+ *
+ * Shortcut Display Order
+ * When the launcher show the shortcuts for a launcher icon, the showing order should be the
+ * following:
+ *
+ *
+ * Rate Limiting
+ *
+ * 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}.
+ *
+ *
+ *
+ *
+ * Resetting rate-limiting for testing
+ *
+ * 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.
+ *
+ * adb shell cmd shortcut reset-throttling [ --user USER-ID ]
+ *
+ *
+ * Handling System Locale Change
+ *
+ * Applications should update dynamic and pinned shortcuts when the system locale changes
+ * using the {@link Intent#ACTION_LOCALE_CHANGED} broadcast.
+ *
+ * Backup and Restore
*
- * Pinned shortcuts will be backed up and restored across devices. This means all information
- * within shortcuts, including IDs, must be meaningful on different devices.
+ * 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.
+ *
+ * What will be backed up and what will not be backed up
*
- *
- *
*
+ * APIs for launcher
+ *
+ * public class MainActivity extends Activity {
+ * public void onCreate(Bundle savedInstanceState) {
+ * super.onCreate(savedInstanceState);
*
- * Launcher applications should use {@link LauncherApps} to get shortcuts that are published from
- * applications. Launcher applications can also pin shortcuts with
- * {@link LauncherApps#pinShortcuts(String, List, UserHandle)}.
+ * ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
+ *
+ * if (shortcutManager.getDynamicShortcuts().size() == 0) {
+ * // Application restored; re-publish dynamic shortcuts.
+ *
+ * if (shortcutManager.getPinnedShortcuts().size() > 0) {
+ * // Pinned shortcuts have been restored. use updateShortcuts() to make sure
+ * // they have up-to-date information.
+ * }
+ * }
+ * }
+ * :
+ *
+ * }
+ *
+ *
+ *
+ * Backup/restore and shortcut IDs
+ *
+ * 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.
+ *
+ *
+ * Report Shortcut Usage and Prediction
+ *
+ * Launcher applications may be capable of predicting which shortcuts will most likely be used at
+ * the moment with the shortcut usage history data.
+ *
+ * Launcher API
+ *
+ * {@link LauncherApps} provides APIs for launcher applications to access shortcuts.
*/
public class ShortcutManager {
private static final String TAG = "ShortcutManager";
@@ -110,14 +382,15 @@ public class ShortcutManager {
/**
* Publish a list of shortcuts. All existing dynamic shortcuts from the caller application
- * will be replaced.
+ * will be replaced. If there's already pinned shortcuts with the same IDs, they will all be
+ * updated, unless they're immutable.
*
*