Shortcuts in the app are designed to do common tasks in the app from the launcher screen. Certain screens can be accessed by long-pressing the app icon and selecting the appropriate shortcut.
Types of AppShortcuts
- Static Shortcuts
- Dynamic Shortcuts
- Pinned Shortcuts
Static Shortcut
These shortcuts have been pre-programmed. They are included in your.apk file. Until you launch a new version of your program, their number and activities remain the same.
Dynamic Shortcut
These shortcuts are created on the fly and added to the list of shortcuts. They can be generated using usage statistics and can evolve over time. To update your dynamic shortcuts, you don’t need to publish a new version of your app.
Pinned Shortcuts
These are used for certain actions that are initiated by the user. A user could want to pin a specific website to the launcher, for example. This is advantageous because it allows the user to complete a specific operation, such as browsing a website in one step, faster than if they used a normal browser instance.
How can we put that into practice?
Static Shortcuts
1st step: We need to add some meta-data to the launcher Activity, so add the following code snippet to your AndroidManifest.xml file. If you don’t, your shortcuts won’t appear. Any activity with the purpose filter is set to action in practice. The android resource specifies the location of the shortcut files in your resource folder.
image by author
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="com.kl.appshortcut"> | |
<application | |
android:allowBackup="true" | |
android:icon="@mipmap/ic_launcher" | |
android:label="@string/app_name" | |
android:roundIcon="@mipmap/ic_launcher_round" | |
android:supportsRtl="true" | |
android:theme="@style/Theme.AppShortcut"> | |
<activity android:name="com.kl.appshortcut.MainActivity3" /> | |
<activity android:name="com.kl.appshortcut.MainActivity2" /> | |
<activity android:name="com.kl.appshortcut.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> | |
</application> | |
</manifest> |
2nd Step: Navigate to shortcuts.xml, which contains the shortcut definitions. set tools:targetApi=”25″ because it’s a good idea to do so as this feature is only available on API levels 25 and up. To see the shortcuts, run your program on your emulator or device once it’s finished.
<?xml version="1.0" encoding="utf-8"?> | |
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
tools:targetApi="25"> | |
<shortcut | |
android:shortcutId="explore" | |
android:enabled="true" | |
android:icon="@drawable/ic_explore" | |
android:shortcutShortLabel="@string/explore" | |
android:shortcutLongLabel="@string/explore" | |
android:shortcutDisabledMessage="@string/explore"> | |
<intent | |
android:action="android.intent.action.VIEW" | |
android:targetPackage="com.kl.appshortcut" | |
android:targetClass="com.kl.appshortcut.MainActivity"> | |
<!-- <extra | |
android:name="key" | |
android:value="value"/>--> | |
<!-- If your shortcut is associated with multiple intents, include them | |
here. The last intent in the list determines what the user sees when | |
they launch this shortcut. --> | |
</intent> | |
<categories android:name="android.shortcut.conversation" /> | |
</shortcut> | |
<shortcut | |
android:shortcutId="maskup" | |
android:enabled="true" | |
android:icon="@drawable/ic_masks" | |
android:shortcutShortLabel="@string/maskup" | |
android:shortcutLongLabel="@string/maskup" | |
android:shortcutDisabledMessage= "@string/maskup"> | |
<intent | |
android:action="android.intent.action.VIEW" | |
android:targetPackage="com.kl.appshortcut" | |
android:targetClass="com.kl.appshortcut.MainActivity2"> | |
</intent> | |
<categories android:name="android.shortcut.conversation" /> | |
</shortcut> | |
<shortcut | |
android:shortcutId="store" | |
android:enabled="true" | |
android:icon="@drawable/ic_store" | |
android:shortcutShortLabel="@string/store" | |
android:shortcutLongLabel="@string/store" | |
android:shortcutDisabledMessage="@string/store"> | |
<intent | |
android:action="android.intent.action.VIEW" | |
android:targetPackage="com.kl.appshortcut" | |
android:targetClass="com.kl.appshortcut.MainActivity3"> | |
</intent> | |
<categories android:name="android.shortcut.conversation" /> | |
</shortcut> | |
</shortcuts> |
Dynamic Shortcuts
The second form of shortcut is dynamic shortcuts, which require the use of the ShortcutManager to interact with (create, destroy, and update). You may obtain a hold of a ShortcutManager by going to
val shortcutManager = getSystemService(ShortcutManager::class.java)
Below is the code snippet for shortcuts.
package com.kl.appshortcut | |
import android.annotation.TargetApi | |
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.os.Bundle | |
import android.widget.Button | |
import androidx.appcompat.app.AppCompatActivity | |
class MainActivity : AppCompatActivity() { | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
buttons() | |
} | |
private fun buttons() { | |
findViewById<Button>(R.id.button2).setOnClickListener { | |
openURL() | |
} | |
findViewById<Button>(R.id.button4).setOnClickListener { | |
removeShortcuts() | |
} | |
} | |
@TargetApi(25) | |
private fun openURL() { | |
val shortcutManager = getSystemService(ShortcutManager::class.java) | |
val intent = Intent(applicationContext, MainActivity::class.java) | |
intent.action = Intent.ACTION_VIEW | |
val shortcut1 = ShortcutInfo.Builder(applicationContext, "mask_up") | |
.setShortLabel("MaskUp Dynamic") | |
.setRank(0) | |
.setLongLabel("Open Maskup Dynamic") | |
.setIcon(Icon.createWithResource(applicationContext, R.drawable.ic_masks)) | |
.setIntent(intent) | |
.build() | |
val shortcut2 = ShortcutInfo.Builder(applicationContext, "web_link") | |
.setShortLabel("google Dynamic") | |
.setRank(1) | |
.setLongLabel("Open google Dynamic") | |
.setIcon(Icon.createWithResource(applicationContext, R.drawable.ic_web)) | |
.setIntent( | |
Intent( | |
Intent.ACTION_VIEW, | |
Uri.parse("https://www.google.com/") | |
) | |
) | |
.build() | |
shortcutManager?.dynamicShortcuts = listOf(shortcut1, shortcut2) | |
} | |
@TargetApi(25) | |
private fun removeShortcuts() { | |
val manager = getSystemService(ShortcutManager::class.java) | |
manager.removeAllDynamicShortcuts() | |
} | |
} |
Job Offers
Because ShortcutManager is a system service, it must be in an activity. Also, as this only works on Android 7.1, it’s a good idea to add the annotation @TargetApi(25) to this code to avoid compile errors and to perform a version check before calling these methods.
In the shortcuts pane, the method setRank() is used to arrange the dynamic shortcuts. It is used to determine where the shortcut should appear in the list, with 0 (zero) being the lowest.
Now that we’ve created our shortcut, we’ll need to make it a Dynamic Shortcut.
shortcutManager?.dynamicShortcuts = list0f(shortcut1, shortcut2)
The dynamic Shortcuts method accepts an Array as input. I’ve made a list because we have two shortcuts.
All dynamic shortcuts will be removed with
manager.removeAllDynamicShortcuts().
Start your app and hold down the long-press button on the app icon in the launcher. Something along these lines should be seen:
image by author
Limitation
The present API supports up to five different shortcuts at any given moment, according to the official Android docs. However, it is strongly advised that you utilize no more than four of them.
Another constraint is the present device’s launcher. App Shortcuts are not yet supported by all launchers. That is, we must test this new feature on as many launchers as possible before releasing it.
The source code can be found on Github.
Thank you for taking the time to read this article. If you found this post to be useful and interesting, please clap and recommend it.
if I got something wrong, mention it in the comments. I would love to improve.
This article was originally published on proandroiddev.com on June 15, 2022