Android N App Shortcuts

Filed Under: Android

Android N brought App Shortcuts for developers and users. In this tutorial, we’ll be creating a sample application using App Shortcuts.

App Shortcuts

App Shortcuts are designed to do common actions in the application from the launcher screen.
We can reach certain screens by just long pressing the app icon and clicking the respective shortcut.
As of Android N, each application can display a maximum of 5 shortcuts.

App Shortcuts are of two types:

  • Static Shortcuts – These are defined in the resource file. To change them you must re-deploy your application
  • Dynamic Shortcuts – These can be created dynamically using ShortcutManager API
You can keep a check of the most visited screens in your app and accordingly create dynamic shortcuts for them.

Some come use cases of App Shortcuts are, sending an email, Booking cab/Ordering Food, Redialling a number etc.

To implement App Shortcuts, you must use Android SDK 25 or above.

Static Shortcuts

Let’s look at the implementation of Static Shortcuts.
To create static shortcuts you must create an XML file with the shortcuts tag as the root one.

Your static_shortcuts.xml will be under xml under res folder and will look like this:


<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
    <shortcut
        android:enabled="true"
        android:icon="@drawable/ic_home_black_24dp"
        android:shortcutId="main_activity"
        android:shortcutLongLabel="@string/shortcut1_long"
        android:shortcutShortLabel="@string/shortcut1_short">
        <intent
            android:action="android.intent.action.VIEW"
            android:targetClass="com.journaldev.androidnappshortcuts.MainActivity"
            android:targetPackage="com.journaldev.androidnappshortcuts"/>
    </shortcut>

    <shortcut
        android:enabled="true"
        android:icon="@drawable/ic_important_devices_black_24dp"
        android:shortcutDisabledMessage="@string/disabled_msg"
        android:shortcutId="SecondActivity"
        android:shortcutLongLabel="@string/shortcut2_long"
        android:shortcutShortLabel="@string/shortcut2_short">

        <intent
            android:action="android.intent.action.MAIN"
            android:targetClass="com.journaldev.androidnappshortcuts.MainActivity"
            android:targetPackage="com.journaldev.androidnappshortcuts" />

        <intent
            android:action="android.intent.action.VIEW"
            android:targetClass="com.journaldev.androidnappshortcuts.StaticShortcutActivity"
            android:targetPackage="com.journaldev.androidnappshortcuts">

            <extra
                android:name="key"
                android:value="Static Shortcut 2 Extras Message" />

        </intent>
    </shortcut>


</shortcuts>
By default, when you launch an activity from the shortcut intent and press back, the application returns to the home launcher. If you want to return to the previous screen in the navigation flow, you can specify multiple intents as we did in the second shortcut in the snippet above.

Following are some of the inferences that we can draw from the above snippet:

  • android:shortcutId – Refers to the unique identifer of the shortcut.
  • shortcutShortLabel – Here we set the string to be displayed in the shortcut. This contains the shorthand form. For the long string, we use android:shortcutLongLabel
  • android:icon – Here we set the icon which is shown on the left of the shortcut.
  • intent – Here we pass on the intent for the shortcut. Inside the intent, we must set the action, target class and target package names, all fully qualified paths.
  • extras – This goes inside the intent tag. We can pass Bundle extras here.

In order to integrate the above static shortcuts in our application, we must set them in the launcher activity meta-data tag.


<meta-data
                android:name="android.app.shortcuts"
                android:resource="@xml/static_shortcuts" />

Dynamic Shortcuts

Dynamic Shortcuts can be created, removed, updated at runtime without the need to re-deploy the application.

For this, we need the ShortcutManager and ShortcutInfo.Builder to create individual shortcuts.

ShortcutManager can be created in activity since it uses the getSystemService.

The following code gets all the static and dynamic shortcuts from the shortcut manager:


// Get all static shortcuts 
List<ShortcutInfo> staticShortcuts = shortcutManager.getManifestShortcuts();

// Get all dynamic shortcuts 
List<ShortcutInfo> dynamicShortcuts = shortcutManager.getDynamicShortcuts();

setDynamicShortcuts is used to set the collection of dynamic shortcuts (ShorcutInfo) defined on the ShortcutManager instance

updateDynamicShortcuts() is used to change already defined dynamic shortcut(s).

Best Practices for Shortcuts

  • Don’t use more than 5 shortcuts at a time – Typically, most launchers can’t display more than 4 shortcuts at a time.
  • Check Dynamic Shortcuts exists every time you launch the app – Dynamic shortcuts aren’t preserved when a user restores your application from a backup. Hence it is a good practice to use getDynamicShortcuts() to check for dynamic shortcuts every time.
  • Maintain short label names – Generally, the short length of shortcut labels is 10 characters to keep the name of the shortcut as short as possible.

In the next section, we’ll implement the shortcuts in our Android Application.

Project Structure

Android N App Shortcuts Project

Android N App Shortcuts Project

Code

The AndroidManifest.xml file looks like this:

Android N App Shortcuts Manifest

Android N App Shortcuts Manifest

The code for the activity_main.xml layout is given below:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Home Screen" />


    <Button
        android:id="@+id/btnNext"
        android:text="Second Screen"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btnDynamicShortcut"
        android:text="Create Dynamic Shortcuts"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />


    <Button
        android:id="@+id/btnRemoveShortcut"
        android:text="Remove Dynamic Shortcuts"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />



</LinearLayout>

The code for the MainActivity.java class is given below:


package com.journaldev.androidnappshortcuts;

import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.util.Arrays;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    Button btnDynamicShortcut, btnRemoveShortcut, btnNext;

    String ACTION_KEY = "anything.any";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnDynamicShortcut = findViewById(R.id.btnDynamicShortcut);
        btnRemoveShortcut = findViewById(R.id.btnRemoveShortcut);
        btnNext = findViewById(R.id.btnNext);

        btnNext.setOnClickListener(this);
        btnDynamicShortcut.setOnClickListener(this);
        btnRemoveShortcut.setOnClickListener(this);

        if (ACTION_KEY.equals(getIntent().getAction())){
            Toast.makeText(getApplicationContext(),"First Dynamic Shortcut clicked",Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.btnNext:
                startActivity(new Intent(MainActivity.this, StaticShortcutActivity.class));
                break;
            case R.id.btnDynamicShortcut:
                createSimpleDynamicShortcut();
                break;
            case R.id.btnRemoveShortcut:
                removeShortcuts();
                break;
        }
    }

    private void createSimpleDynamicShortcut() {



        ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);

        Intent intent1 = new Intent(getApplicationContext(), MainActivity.class);
        intent1.setAction(ACTION_KEY);

        ShortcutInfo shortcut1 = new ShortcutInfo.Builder(this, "dShortcut1")
                .setIntent(intent1)
                .setRank(1)
                .setLongLabel("Dynamic Shortcut 1")
                .setShortLabel("This is the shortcut 1")
                .setIcon(Icon.createWithResource(this, R.drawable.ic_home_black_24dp))
                .build();


        ShortcutInfo shortcut2 = new ShortcutInfo.Builder(this, "web_link")
                .setRank(0)
                .setShortLabel("Journaldev.com")
                .setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.journaldev.com")))
                .build();


        shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut1, shortcut2));

        //shortcutManager.disableShortcuts(Arrays.asList(shortcut1.getId()));

    }

    private void removeShortcuts() {
        ShortcutManager manager = getSystemService(ShortcutManager.class);
        manager.removeAllDynamicShortcuts();

    }
}

setRank() is used to order the dynamic shortcuts in the shortcuts pane.

The code for the StaticShortcutActivity.java is given below:


package com.journaldev.androidnappshortcuts;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.TextView;

public class StaticShortcutActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_static_shortcut);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        TextView textView = findViewById(R.id.tvTitle);

        if (getIntent() != null && getIntent().getStringExtra("key") != null) {
            String bundleString = getIntent().getStringExtra("key");
            textView.setText(bundleString);
        }

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

}

You can get the layout of the above activity from the source code at the end of this tutorial.

The output of the above application in action is given below:

Android N App Shortcuts Output

Android N App Shortcuts Output

That’s a wrap up for this tutorial. You can download the project from the link below or always browse the full source code in our Github Repository.

Comments

  1. George Petre says:

    This article is so nice!

    Thank you

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages