ShortcutManager
public
class
ShortcutManager
extends Object
| java.lang.Object | |
| ↳ | android.content.pm.ShortcutManager |
The ShortcutManager manages an app's shortcuts. Shortcuts provide users
with quick access to activities other than an app's main activity in the currently-active
launcher. For example,
an email app may publish the "compose new email" action, which will directly open the
compose activity. The ShortcutInfo class contains information about each of the
shortcuts themselves.
Static Shortcuts and Dynamic Shortcuts
There are two ways to publish shortcuts: static shortcuts and dynamic shortcuts.
- Static shortcuts are declared in a resource
XML file, which is referenced in the publisher app's
AndroidManifest.xmlfile. Static shortcuts are published when an app is installed, and the details of these shortcuts change when an app is upgraded with an updated XML file. Static shortcuts are immutable, and their definitions, such as icons and labels, cannot be changed dynamically without upgrading the publisher app. - Dynamic shortcuts are published at runtime using this class's APIs. Apps can publish, update, and remove dynamic shortcuts at runtime.
Only main activities—activities that handle the MAIN action and the
LAUNCHER category—can have shortcuts.
If an app has multiple main activities, these activities have different sets
of shortcuts.
Static shortcuts and dynamic shortcuts are shown in the currently active launcher when the user long-presses on an app's launcher icon.
Note: The actual gesture may be different depending on the launcher app.
Each launcher icon can have at most getMaxShortcutCountPerActivity() number of
static and dynamic shortcuts combined.
Pinning Shortcuts
Launcher apps allow users to pin shortcuts so they're easier to access. Both static and dynamic shortcuts can be pinned. Pinned shortcuts cannot be removed by publisher apps; they're removed only when the user removes them, when the publisher app is uninstalled, or when the user performs the clear data action on the publisher app from the device's Settings app.
However, the publisher app can disable pinned shortcuts so they cannot be started. See the following sections for details.
Updating and Disabling Shortcuts
When a dynamic shortcut is pinned, even when the publisher removes it as a dynamic shortcut,
the pinned shortcut will still be visible and launchable. This allows an app to have
more than getMaxShortcutCountPerActivity() number of shortcuts.
For example, suppose getMaxShortcutCountPerActivity() is 5:
- A chat app publishes 5 dynamic shortcuts for the 5 most recent conversations (c1, c2, ..., c5).
- The user pins all 5 of the shortcuts.
- Later, the user has started 3 additional conversations (c6, c7, and c8), so the publisher app re-publishes its dynamic shortcuts. The new dynamic shortcut list is: c4, c5, ..., c8. The publisher app has to remove c1, c2, and c3 because it can't have more than 5 dynamic shortcuts.
- However, even though c1, c2, and c3 are no longer dynamic shortcuts, the pinned shortcuts for these conversations are still available and launchable.
- At this point, the user can access a total of 8 shortcuts that link to activities in the publisher app, including the 3 pinned shortcuts, even though an app can have at most 5 dynamic shortcuts.
- The app can use
updateShortcuts(List)to update any of the existing 8 shortcuts, when, for example, the chat peers' icons have changed. TheaddDynamicShortcuts(List)andsetDynamicShortcuts(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 usedisableShortcuts(List), which removes the specified dynamic shortcuts and also makes any specified pinned shortcuts un-launchable. ThedisableShortcuts(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 theres/xml/shortcuts.xmlfile:<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
android:enabled- Default is
true. Can be set tofalsein 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 withenabled="false". android:icon- Shortcut icon.
android:shortcutShortLabel- Mandatory shortcut short label.
See
setShortLabel(CharSequence). android:shortcutLongLabel- Shortcut long label.
See
setLongLabel(CharSequence). android:shortcutDisabledMessage- When
android:enabledis set tofalse, this attribute is used to display a custom disabled message. intent- Intent to launch when the user selects the shortcut.
android:actionis 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. SeeTaskStackBuilderfor details. categories- Specify shortcut categories. Currently only
SHORTCUT_CATEGORY_CONVERSATIONis defined in the framework.
Publishing Dynamic Shortcuts
Apps can publish dynamic shortcuts with
setDynamicShortcuts(List)oraddDynamicShortcuts(List). TheupdateShortcuts(List)method can also be used to update existing, mutable shortcuts. UseremoveDynamicShortcuts(List)orremoveAllDynamicShortcuts()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
Intentflags. Typically,FLAG_ACTIVITY_CLEAR_TASKis 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
setIntents(Intent[])method can be used instead ofsetIntent(Intent)withTaskStackBuilderin 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
Intentobjects 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
FLAG_ACTIVITY_NEW_TASKandFLAG_ACTIVITY_CLEAR_TASKset. 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 inonCreate(Bundle), then callsfinish(). The first activity should include an attribute setting ofandroid:taskAffinity=""in the app'sAndroidManifest.xmlfile, 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)oraddDynamicShortcuts(List), rather than updating the existing shortcut withupdateShortcuts(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:- First show static shortcuts
(if
isDeclaredInManifest()istrue), and then show dynamic shortcuts (ifisDynamic()istrue). - Within each category of shortcuts (static and dynamic), sort the shortcuts in order
of increasing rank according to
getRank().
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 useaddDynamicShortcuts(List)andsetDynamicShortcuts(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), andupdateShortcuts(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 returnfalse.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:
- An app comes to the foreground.
- The system locale changes.
- The user performs the inline reply action on a notification.
When rate-limiting is active,
isRateLimitingActive()returnstrue.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
adbcommand 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
ACTION_LOCALE_CHANGEDbroadcast.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 itsAndroidManifest.xmlfile, pinned shortcuts are backed up automatically and are restored when the user sets up a new device.Categories of shortcuts that are backed up
- Pinned shortcuts are backed up. Bitmap icons are not backed up by the system,
so launcher apps should back them up and restore them so that the user still sees icons
for pinned shortcuts on the launcher. Apps can always use
updateShortcuts(List)to re-publish icons. - Static shortcuts aren't backed up, but when an app is re-installed on a new
device, they are re-published from the
AndroidManifest.xmlfile. - Dynamic shortcuts aren't 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
TheLauncherAppsclass 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.Summary
Public methods
booleanaddDynamicShortcuts(List<ShortcutInfo> shortcutInfoList)Publish the list of dynamic shortcuts.
voiddisableShortcuts(List<String> shortcutIds)Disable pinned shortcuts.
voiddisableShortcuts(List<String> shortcutIds, CharSequence disabledMessage)Disable pinned shortcuts, showing the user a custom error message when they try to select the disabled shortcuts.
voidenableShortcuts(List<String> shortcutIds)Re-enable pinned shortcuts that were previously disabled.
List<ShortcutInfo>getDynamicShortcuts()Return all dynamic shortcuts from the caller app.
intgetIconMaxHeight()Return the max height for icons, in pixels.
intgetIconMaxWidth()Return the max width for icons, in pixels.
List<ShortcutInfo>getManifestShortcuts()Return all static (manifest) shortcuts from the caller app.
intgetMaxShortcutCountPerActivity()Return the maximum number of static and dynamic shortcuts that each launcher icon can have at a time.
List<ShortcutInfo>getPinnedShortcuts()Return all pinned shortcuts from the caller app.
booleanisRateLimitingActive()Return
truewhen rate-limiting is active for the caller app.voidremoveAllDynamicShortcuts()Delete all dynamic shortcuts from the caller app.
voidremoveDynamicShortcuts(List<String> shortcutIds)Delete dynamic shortcuts by ID.
voidreportShortcutUsed(String shortcutId)Apps 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 app that is equivalent to selecting the shortcut.
booleansetDynamicShortcuts(List<ShortcutInfo> shortcutInfoList)Publish the list of shortcuts.
booleanupdateShortcuts(List<ShortcutInfo> shortcutInfoList)Update all existing shortcuts with the same IDs.
Inherited methods
From
class
java.lang.ObjectPublic methods
addDynamicShortcuts
Added in API level 25boolean addDynamicShortcuts (List<ShortcutInfo> shortcutInfoList)
Publish the list of dynamic shortcuts. If there are already dynamic or pinned shortcuts with the same IDs, each mutable shortcut is updated.
This API will be rate-limited.
Parameters shortcutInfoListListReturns booleantrueif the call has succeeded.falseif the call is rate-limited.Throws IllegalArgumentExceptionif getMaxShortcutCountPerActivity()is exceeded, or when trying to update immutable shortcuts.IllegalStateExceptionwhen the user is locked. disableShortcuts
Added in API level 25void disableShortcuts (List<String> shortcutIds)
Disable pinned shortcuts. For more details, see the Javadoc for the
ShortcutManagerclass.Parameters shortcutIdsListThrows IllegalArgumentExceptionIf trying to disable immutable shortcuts. IllegalStateExceptionwhen the user is locked. disableShortcuts
Added in API level 25void disableShortcuts (List<String> shortcutIds, CharSequence disabledMessage)
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
ShortcutManagerclass.Parameters shortcutIdsListdisabledMessageCharSequenceThrows IllegalArgumentExceptionIf trying to disable immutable shortcuts. IllegalStateExceptionwhen the user is locked. enableShortcuts
Added in API level 25void enableShortcuts (List<String> shortcutIds)
Re-enable pinned shortcuts that were previously disabled. If the target shortcuts are already enabled, this method does nothing.
Parameters shortcutIdsListThrows IllegalArgumentExceptionIf trying to enable immutable shortcuts. IllegalStateExceptionwhen the user is locked. getDynamicShortcuts
Added in API level 25List<ShortcutInfo> getDynamicShortcuts ()
Return all dynamic shortcuts from the caller app.
Returns List<ShortcutInfo>Throws IllegalStateExceptionwhen the user is locked. getIconMaxHeight
Added in API level 25int getIconMaxHeight ()
Return the max height for icons, in pixels.
Returns intgetIconMaxWidth
Added in API level 25int getIconMaxWidth ()
Return the max width for icons, in pixels.
Returns intgetManifestShortcuts
Added in API level 25List<ShortcutInfo> getManifestShortcuts ()
Return all static (manifest) shortcuts from the caller app.
Returns List<ShortcutInfo>Throws IllegalStateExceptionwhen the user is locked. getMaxShortcutCountPerActivity
Added in API level 25int getMaxShortcutCountPerActivity ()
Return the maximum number of static and dynamic shortcuts that each launcher icon can have at a time.
Returns intgetPinnedShortcuts
Added in API level 25List<ShortcutInfo> getPinnedShortcuts ()
Return all pinned shortcuts from the caller app.
Returns List<ShortcutInfo>Throws IllegalStateExceptionwhen the user is locked. isRateLimitingActive
Added in API level 25boolean isRateLimitingActive ()
Return
truewhen rate-limiting is active for the caller app.See the class level javadoc for details.
Returns booleanThrows IllegalStateExceptionwhen the user is locked. removeAllDynamicShortcuts
Added in API level 25void removeAllDynamicShortcuts ()
Delete all dynamic shortcuts from the caller app.
Throws IllegalStateExceptionwhen the user is locked. removeDynamicShortcuts
Added in API level 25void removeDynamicShortcuts (List<String> shortcutIds)
Delete dynamic shortcuts by ID.
Parameters shortcutIdsListThrows IllegalStateExceptionwhen the user is locked. reportShortcutUsed
Added in API level 25void reportShortcutUsed (String shortcutId)
Apps 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 app that is equivalent to selecting the shortcut. For more details, see the Javadoc for the
ShortcutManagerclassThe information is accessible via
queryEvents(long, long)Typically, launcher apps use this information to build a prediction model so that they can promote the shortcuts that are likely to be used at the moment.Parameters shortcutIdStringThrows IllegalStateExceptionwhen the user is locked. setDynamicShortcuts
Added in API level 25boolean setDynamicShortcuts (List<ShortcutInfo> shortcutInfoList)
Publish the list of shortcuts. All existing dynamic shortcuts from the caller app will be replaced. If there are already pinned shortcuts with the same IDs, the mutable pinned shortcuts are updated.
This API will be rate-limited.
Parameters shortcutInfoListListReturns booleantrueif the call has succeeded.falseif the call is rate-limited.Throws IllegalArgumentExceptionif getMaxShortcutCountPerActivity()is exceeded, or when trying to update immutable shortcuts.IllegalStateExceptionwhen the user is locked. updateShortcuts
Added in API level 25boolean updateShortcuts (List<ShortcutInfo> shortcutInfoList)
Update all existing shortcuts with the same IDs. Target shortcuts may be pinned and/or dynamic, but they must not be immutable.
This API will be rate-limited.
Parameters shortcutInfoListListReturns booleantrueif the call has succeeded.falseif the call is rate-limited.Throws IllegalArgumentExceptionIf trying to update immutable shortcuts. IllegalStateExceptionwhen the user is locked.
Classes
- ActivityInfo
- ActivityInfo.WindowLayout
- ApplicationInfo
- ApplicationInfo.DisplayNameComparator
- ComponentInfo
- ConfigurationInfo
- FeatureGroupInfo
- FeatureInfo
- InstrumentationInfo
- LabeledIntent
- LauncherActivityInfo
- LauncherApps
- LauncherApps.Callback
- LauncherApps.ShortcutQuery
- PackageInfo
- PackageInstaller
- PackageInstaller.Session
- PackageInstaller.SessionCallback
- PackageInstaller.SessionInfo
- PackageInstaller.SessionParams
- PackageItemInfo
- PackageItemInfo.DisplayNameComparator
- PackageManager
- PackageStats
- PathPermission
- PermissionGroupInfo
- PermissionInfo
- ProviderInfo
- ResolveInfo
- ResolveInfo.DisplayNameComparator
- ServiceInfo
- ShortcutInfo
- ShortcutInfo.Builder
- ShortcutManager
- Signature
Exceptions