Skip navigation links
android.content.pm

Class ShortcutManager

The addDynamicShortcuts(List) and setDynamicShortcuts(List) methods can also be used to update existing shortcuts with the same IDs, but they cannot be used for updating non-dynamic, pinned shortcuts because these two methods try to convert the given lists of shortcuts to dynamic shortcuts.

Disabling Static Shortcuts

When an app is upgraded and the new version no longer uses a static shortcut that appeared in the previous version, this deprecated shortcut will no longer be published as a static shortcut.

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 static shortcut, but it's still immutable. Therefore, it cannot be updated using this class's APIs.

Disabling Dynamic Shortcuts

Sometimes pinned shortcuts become obsolete and may not be usable. For example, a pinned shortcut to a group chat becomes unusable when the associated group chat is deleted. In cases like this, apps should use disableShortcuts(List), which removes the specified dynamic shortcuts and also makes any specified pinned shortcuts un-launchable. The 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.

Publishing Static Shortcuts

In order to add static shortcuts to your app, first add <meta-data android:name="android.app.shortcuts" /> to your main activity in AndroidManifest.xml:

<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 your app's static shortcuts in the res/xml/shortcuts.xml file:
<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_long_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" />
    <!-- If your shortcut is associated with multiple intents, include them
         here. The last intent in the list is what the user sees when they
         launch this shortcut. -->
    <categories android:name="android.shortcut.conversation" />
  </shortcut>
  <!-- Specify more shortcuts here. -->
</shortcuts>
 
The following list includes descriptions for the different attributes within a static shortcut:
android:shortcutId
Mandatory shortcut ID.

This must be a string literal. A resource string, such as @string/foo, cannot be used.

android:enabled
Default is true. Can be set to false in order to disable a static shortcut that was published in a previous version and set a custom disabled message. If a custom disabled message is not needed, then a static shortcut can be simply removed from the XML file rather than keeping it with enabled="false".
android:icon
Shortcut icon.
android:shortcutShortLabel
Mandatory shortcut short label. See ShortcutInfo.Builder.setShortLabel(CharSequence).

This must be a resource string, such as @string/shortcut_label.

android:shortcutLongLabel
Shortcut long label. See ShortcutInfo.Builder.setLongLabel(CharSequence).

This must be a resource string, such as @string/shortcut_long_label.

android:shortcutDisabledMessage
When android:enabled is set to false, this attribute is used to display a custom disabled message.

This must be a resource string, such as @string/shortcut_disabled_message.

intent
Intent to launch when the user selects the shortcut. android:action is mandatory. See Using intents for the other supported tags. You can provide multiple intents for a single shortcut so that the last defined activity is launched with the other activities in the back stack. See TaskStackBuilder for details.
categories
Specify shortcut categories. Currently only ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION is defined in the framework.

Publishing Dynamic Shortcuts

Apps can publish dynamic shortcuts with setDynamicShortcuts(List) or addDynamicShortcuts(List). The updateShortcuts(List) method can also be used to update existing, mutable shortcuts. Use removeDynamicShortcuts(List) or removeAllDynamicShortcuts() to remove dynamic shortcuts.

The following code snippet shows how to create a single dynamic shortcut:

ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);

ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "id1")
    .setShortLabel("Web site")
    .setLongLabel("Open the web site")
    .setIcon(Icon.createWithResource(context, R.drawable.icon_website))
    .setIntent(new Intent(Intent.ACTION_VIEW,
                   Uri.parse("https://www.mysite.example.com/")))
    .build();

shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut));
 

Shortcut Intents

Dynamic shortcuts can be published with any set of Intent flags. Typically, Intent.FLAG_ACTIVITY_CLEAR_TASK is specified, possibly along with other flags; otherwise, if the app is already running, the app is simply brought to the foreground, and the target activity may not appear.

The ShortcutInfo.Builder.setIntents(Intent[]) method can be used instead of ShortcutInfo.Builder.setIntent(Intent) with 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 from the same app will be shown instead of the user being navigated back to the launcher.

Static shortcuts can also have multiple intents to achieve the same effect. In order to associate multiple Intent objects with a shortcut, simply list multiple <intent> elements within a single <shortcut> element. The last intent specifies what the user sees when they launch a shortcut.

Static shortcuts cannot have custom intent flags. The first intent of a static shortcut will always have Intent.FLAG_ACTIVITY_NEW_TASK and Intent.FLAG_ACTIVITY_CLEAR_TASK set. This means, when the app is already running, all the existing activities will be destroyed when a static shortcut is launched. If this behavior is not desirable, you can use a trampoline activity, or an invisible activity that starts another activity in Activity.onCreate(android.os.Bundle), then calls Activity.finish(). The first activity should include an attribute setting of android:taskAffinity="" in the app's AndroidManifest.xml file, and the intent within the static shortcut should point at this first activity.

Showing New Information in a Shortcut

In order to avoid confusion, you should not use updateShortcuts(List) to update a shortcut so that it contains conceptually different information.

For example, a phone app may publish the most frequently called contact as a dynamic shortcut. Over time, this contact may change. When it does, the app should represent the changed contact with a new shortcut that contains a different ID, using either setDynamicShortcuts(List) or addDynamicShortcuts(List), rather than updating the existing shortcut with updateShortcuts(List). This is because when the shortcut is pinned, changing it to reference a different contact will likely confuse the user.

On the other hand, when the contact's information has changed, such as the name or picture, the app should use updateShortcuts(List) so that the pinned shortcut is updated too.

Shortcut Display Order

When the launcher displays the shortcuts that are associated with a particular launcher icon, the shortcuts should appear in the following order:

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 updateShortcuts(List). You can also use addDynamicShortcuts(List) and setDynamicShortcuts(List).

Ranks are auto-adjusted so that they're unique for each target activity in each category (static or dynamic). For example, if there are 3 dynamic shortcuts with ranks 0, 1 and 2, 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.

Rate Limiting

Calls to setDynamicShortcuts(List), addDynamicShortcuts(List), and updateShortcuts(List) may be rate-limited when called by background apps, or apps with no foreground activity or service. When you attempt to call these methods from a background app after exceeding the rate limit, these APIs return false.

Apps with a foreground activity or service are not rate-limited.

Rate-limiting is reset upon certain events, so that even background apps can call these APIs until the rate limit is reached again. These events include the following:

When rate-limiting is active, isRateLimitingActive() returns true.

Resetting rate-limiting for testing

If your app 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 Changes

Apps should update dynamic and pinned shortcuts when the system locale changes using the Intent.ACTION_LOCALE_CHANGED broadcast.

When the system locale changes, rate-limiting is reset, so even background apps can add and update dynamic shortcuts until the rate limit is reached again.

Backup and Restore

When an app has the android:allowBackup="true" attribute assignment included in its AndroidManifest.xml file, pinned shortcuts are backed up automatically and are restored when the user sets up a new device.

Categories of shortcuts that are backed up

Because dynamic shortcuts are not restored, it is recommended that apps check currently-published dynamic shortcuts using getDynamicShortcuts() each time they are launched, and they should re-publish dynamic shortcuts when necessary.

public class MainActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ShortcutManager shortcutManager =
                getSystemService(ShortcutManager.class);

        if (shortcutManager.getDynamicShortcuts().size() == 0) {
            // Application restored. Need to re-publish dynamic shortcuts.
            if (shortcutManager.getPinnedShortcuts().size() > 0) {
                // Pinned shortcuts have been restored. Use
                // updateShortcuts() to make sure they contain
                // up-to-date information.
            }
        }
    }
    // ...
}
 

Backup/restore and shortcut IDs

Because pinned shortcuts are backed up and restored on new devices, shortcut IDs should contain either stable, constant strings or server-side identifiers, rather than identifiers generated locally that might not make sense on other devices.

Report Shortcut Usage and Prediction

Launcher apps may be capable of predicting which shortcuts will most likely be used at a given time by examining the shortcut usage history data.

In order to provide launchers with such data, publisher apps should report the shortcuts that are used with reportShortcutUsed(String) when a shortcut is selected, 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 navigation app supports "navigate to work" as a shortcut. It should then report when the user selects this shortcut and when the user chooses to navigate to work within the app itself. This helps the launcher app 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.

Launcher API

The LauncherApps class provides APIs for launcher apps to access shortcuts.

Direct Boot and Shortcuts

All shortcut information is stored in credential encrypted storage, so no shortcuts can be accessed when the user is locked.
Skip navigation links