An introduction to Android’s App Shortcuts

Android Nougat 7.1, the newest version of Android at the time of writing this article, comes with several new features.  The one that we will be exploring in this blog post is the App Shortcuts feature.

App Shortcuts allows you to create shortcuts for specific actions within your app that can bring users directly from the launcher to the associated screens. The feature is available on any launcher that supports them, such as Google Now and Pixel launchers. To reveal the shortcuts of an app, simply long-press the launcher icon of that app.

chrome-app-shortcuts

If you are enrolled in the Beta program and got the Android 7.1 Developer Preview, you can find that some of the apps already support App Shortcuts, for example: Camera, Dialer, Messenger, Google Drive, and Youtube. Unfortunately there’s no visual indication on which apps support this feature (at least not at this time), so you will have to long-press on every app’s launcher icon in order to discover the ones that support it.

Adding App Shortcuts to your app

There are 2 ways that can be used to add app shortcuts to your app:  statically (by declaring all the shortcuts in a resource file, also known as manifest shortcuts) and dynamically (by adding the shortcuts at runtime).

First we will take a look at the static approach.

1. Create a resource file: res/xml/shortcuts.xml

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
    
    <shortcut
        android:shortcutId="new_task"
        android:enabled="true"
        android:icon="@drawable/ic_shortcut_new_task"
        android:shortcutLongLabel="@string/shortcut_label_create_new_task"
        android:shortcutShortLabel="@string/shortcut_label_new_task"
        android:shortcutDisabledMessage="@string/shortcut_label_disabled" >
        <intent
            android:action="android.intent.action.VIEW"
            android:targetClass="com.example.vgrec.testshortcuts.NewTaskActivity"
            android:targetPackage="com.example.vgrec.testshortcuts" />
    </shortcut>

    <shortcut
        android:shortcutId="opened_tasks"
        android:enabled="true"
        android:icon="@drawable/ic_shortcut_opened_tasks"
        android:shortcutLongLabel="@string/shortcut_label_view_opened_tasks"
        android:shortcutShortLabel="@string/shortcut_label_opened_tasks"
        android:shortcutDisabledMessage="@string/shortcut_label_disabled" >
        <intent
            android:action="android.intent.action.VIEW"
            android:targetClass="com.example.vgrec.testshortcuts.OpenedTasksActivity"
            android:targetPackage="com.example.vgrec.testshortcuts" />
    </shortcut>

</shortcuts>

Each shortcut defines a series of attributes, like the icon and labels, and also references an intent which is set to launch a specific activity when triggered.
The recommended maximum number of shortcuts is 4, although it is possible to publish up to 5.

Please note that the android:shortcutId attribute is a mandatory attribute. Not declaring it will cause the respective shortcut not to appear in the shortcuts list.

2. Next step is to reference the shortcuts.xml file in the AndroidManifest.xml as metadata to the app’s launcher activity:

<activity android:name=".MainActivity">
     <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>

Any activity that has the intent-filter action set to android.intent.action.MAIN and the category to android.intent.category.LAUNCHER can display app shortcuts.

Having all these pieces in place, the result might look something like this:

android app shortcuts

For testing purposes I used the Android Studio wizard to generate the shortcut icons, but in a production app you should follow the Android Design Guidelines 🙂.

If you tap and drag a shortcut then it will be pinned to the device’s launcher:

android-pinned-app-shortcuts

Have you noticed that the text of the shortcuts in the first image differs from the text of the shortcuts in the second image? Well, that’s what the android:shortcutLongLabel and android:shortcutShortLabel attributes are for.

What about the android:shortcutDisabledMessage? In case a shortcut is disabled it will no longer appear in the shortcuts list. However, if the shortcut is already pinned, it will be simply grayed out and tapping on it will display the message specified by the android:shortcutDisabledMessage attribute.

action_disabled

Adding App Shortcuts dynamically

ShortcutManager is the entry point for manipulating (adding, updating, removing) shortcuts at runtime:

ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);

Intent intent = new Intent(this, NewTaskActivity.class);
intent.setAction(Intent.ACTION_VIEW);

ShortcutInfo shortcut = new ShortcutInfo.Builder(this, getString(R.string.shortcut_id_new_task))
    .setShortLabel(getString(R.string.shortcut_label_new_task))  
    .setLongLabel(getString(R.string.shortcut_label_create_new_task))
    .setIcon(Icon.createWithResource(this, R.drawable.ic_action_add) 
    .setIntent(intent)
    .build();

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

Other methods from ShortcutManager that might be of interest:

updateShortcuts(List ids) – update all existing shortcuts by ID.

removeDynamicShortcuts(List ids) – delete dynamic shortcuts by ID.

disableShortcuts(List ids) – disable dynamic shortcuts by ID.

reportShortcutUsed(String shortcutId) – You want to 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. Typically, launcher applications use this information to build a prediction model so that they can promote the shortcuts that are likely to be used at the moment. (This method works both for static and dynamic shortcuts.)

Please note that attempting to manipulate a static shortcut via the ShortcutManager will throw IllegalArgumentException: Manifest shortcut ID=xyz may not be manipulated via APIs.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s