It has been a few years since I last looked at implementing app shortcuts, and lately I have been looking at them again. I remember implementing them the first time they were released for Android N, but as with life, things have changed a bit.
In this post I want to share some interesting learnings I had whilst implementing static app shortcuts. (Note: This post assumes the reader is familiar with the basic requirements of implementing app shortcuts). As always, all the code for this post is in my Sandbox App.
Android Studio support is… limited.
For this exercise, I am using Android Studio 3.5 Beta 4.
And by limited I mean resource references do not autocomplete at all. This becomes tricky as some of the required attributes can use resource references. The table below shows what those are:
Allowed | Not allowed |
---|---|
shortcutShortLabel |
shortcutId |
shortcutLongLabel |
Intent attributes (targetPackage , targetClass ) |
icon |
My non-scientific test shows that on Pixel launchers, shortcutShortLabel
is used unless shortcutLongLabel
is 17 characters or less.
There are changes in design guidelines between APIs 25 and 26
Android O introduced adaptive icons and if we take into consideration that users can pin shortcuts onto their homescreens, we need to support this format if we want to provide the best possible user experience.
Nick Butcher talked about this in detail in his post on implementing adaptive icons.
Using a VectorDrawable
for the icon foreground as Nick showed, it didn’t seem to like using theme references for the fill colour. Using a resource reference is okay.
Read this post to learn more about designing adaptive icons, and this document for designing app shortcut icons.
Mo’ package names, mo’ files
For each app shortcut we want to support, there needs to be an Intent
associated with it; with each Intent
needing a targetPackage
and a targetClass
. To wit:
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="com.zdominguez.sdksandbox"
android:targetClass="com.zdominguez.sdksandbox.MainActivity" />
This might present a problem if your app have different package names for each build type. Someone has written a function to support variables but unfortunately it does not work on more modern versions of the Gradle Plugin.
This means that we would need multiple shortcuts.xml
files for all build variants that we want to support:
Passing intent extras is possible, but sometimes a trampoline activity comes in handy
If we need to pass some extras to the Activity
we are targetting, we can do so via the XML file:
<intent ...>
<extra android:name="target_tab" android:value="settings" />
</intent>
One important statement that is a bit buried in the documentation for app shortcuts is:
[W]hen the app is already running, all the existing activities in your app are destroyed when a static shortcut is launched.
This is when a trampoline Activity
becomes useful so we can prepare our back stack or even get a handle on some requirements the receiving activity would need (for example, a value to be read from the database). You can read more about trampoline activities here.
Handling up navigation
Similar to how we should handle navigation when starting an Activity
from a notification, we need to consider how the app would behave when the user navigates away from our target Activity
.
Thus, we need to provide multiple Intent
s to the shortcut and the last one in the list would be what the user initially sees.
<shortcut ...>
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="com.zdominguez.sdksandbox"
android:targetClass="com.zdominguez.sdksandbox.MainActivity">
<extra android:name="target_tab" android:value="settings" />
</intent>
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="com.zdominguez.sdksandbox"
android:targetClass="com.zdominguez.sdksandbox.DemoActivity">
</intent>
</shortcut>
It took me a bit longer than I liked to figure out all of this , so I’m writing it down to have a reference for future me.
Make sure to read the rest of the best practices document to learn more.