Exploring Android Q: Sharing Shortcuts

share

A few weeks back we saw the announcement of the Android Q beta release 🎉 With this version of Android comes a collection of exciting changes which we need to get our apps ready for. In this set of articles I’m going to be diving into each one of these so that we are fully prepared for getting our apps ready!

Note: You can find the code for this article here.


As outlined in the beta release notes for Android Q, one of the changes we are seeing some changes into how the direct share functionality of android works. The Direct Share API allows developers to provide direct recipients who we wished to share content with via the share sheet – be it a contact in your favourite messaging app or email, this provides a quick way for your to share content with them directly. However, whilst this feature is pretty neat, the execution of it was never that smooth. One of the big things is the delay in which these contacts are loaded – check out the sample screen share from below:

Mar-26-2019 13-44-00

Credit: Marques Brownlee

You’ll notice here there is a delay in which the direct share options are loaded. This frequently happened to me also whenever I’ve opened the share sheet. On a number of times I’ve accidentally share something with a contact, rather than with an app, because after the delay more options have loaded and pushed my originally selection further down the sheet. To improve on the experience provided by share sheets we now have access to a new approach, known as Sharing Shortcuts. This changes the way in which applications provide these direct options for sharing, meaning that they will be retrieved much quicker when the share sheet is opened, removing some of the clunkiness which would previously occur.

For this to work, we need to provide a list of share targets that will be used at runtime. The way in which this is implemented is very similar to the shortcuts API that we’ve been using in our applications which allows users to easily access features of our app. And similar to how we declare static app shortcuts, defining these share shortcuts begins by declaring a share target within our res/xml directory. Here, we declare a shortcuts element with nested share-target – this target is used to define:

  • Target class: This is used to declare the activity to be launched when the share activity is invoked
  • Mime type: The data type for which the share-target should be shown.
  • Category name: The name of the share category, this will also be used programatically when configuring the share target. It is possible to define multiple categories when it comes to a share-target.

So for example, if I had an activity called ShareActivity that handled plain text shares, then the shortcuts xml file that defines this would look like so:

<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
    <share-target android:targetClass="co.joebirch.androidqplayground.ShareActivity">
        <data android:mimeType="text/plain" />
        <category android:name="co.joebirch.androidqplayground.category.TEXT_SHARE_TARGET" />
    </share-target>
</shortcuts>

Once this has been defined, we need to create a reference to our share shortcuts within our application manifest file:

<activity android:name=".MainActivity">
    ...

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

Next, we need to add our shortcuts to the system ShortcutManager, this is so that the system is aware of our shortcuts and can display them within the system share sheet. Here we’re going to use the Builder for the ShortcutInfoCompat class, this will assist us in creating our shortcuts for display in the share sheet.

ShortcutInfoCompat.Builder(context, Integer.toString(id))
    .setShortLabel(id.toString())
    .setIcon(IconCompat.createWithResource(context, R.drawable.ic_android_black_24dp))
    .setIntent(Intent(Intent.ACTION_DEFAULT))
    .setLongLived()
    .setCategories(setOf(CATEGORY_TEXT_SHARE_TARGET))
    .setPerson(
        Person.Builder()
            .setName(id.toString())
            .build()
    )
    .build()

Whilst you may have used this class before to create application shortcuts, you’ll notice that there are now a few changes as of Android Q:

  • setCategories: Whilst this function of the builder was already previously available, this is now required to be set if you are using share shortcuts. This is so that the system can filter out actions against share intents.
  • setLongLived: When a shortcut is set to be long lived, it means that system services can still access it from the cache even after it has been removed as a dynamic shortcut.
  • setPerson: This can be used to set the Person instance that is associated with this shortcut. Whilst this is not a required property when it comes to share shortcuts, it helps the system to provide appropriate suggestions within the share sheet. Note: There is also a setPersons builder function that can be used to add multiple Person instances.

It’s important to note that these share targets may still need to be updated within your app, as in it might not be a case of adding them a single time. For example, you may be working with a messaging app where the user has added a new friend to talk to or even want to change the share shortcuts based on who the user regularly shares content with.

Once we have our shortcuts we can then use the Shortcut Manager to add our shortcuts:

ShortcutManagerCompat.addDynamicShortcuts(context, shortcuts)

You’ll notice here that we’re making use of the ShortcutManagerCompat class, instead of the ShortcutManager we may have previously used. ShortcutManagerCompat is from AndroidX and provides us with backward compatibility when it comes to working with the DirectShare API that we would have previous used in place of the Sharing Shortcuts. However, if we want to make use of ShortcutManagerCompat then we must add some additional meta-data to the activity that is to be handling the share intent.

<activity android:name=".ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>

    <meta-data
            android:name="android.service.chooser.chooser_target_service"
            android:value="androidx.sharetarget.ChooserTargetServiceCompat" />

</activity>

We can now run our app, invoke a share action and see that our share shortcuts are being shown in the share sheet:

shot

Another important thing to note is that these are still essentially app shortcuts. So when we add them using the ShortcutManager (or ShortcutManagerCompat) – even though they have been added as share targets, they will still be shown from the app launcher when long pressing on an application icon.


Whilst not all application may make use of the new Sharing Shortcuts functionality, it’s definitely still something that will improve the experience of the Android System if you are yourself an Android user. If you are working on an application that currently makes use of the DirectShare API then it is in your best interest to migrate to this new approach. When the device is running Android Q, share targets that are using the ShortcutManager will be placed at a high priority than those added via the DirectShare API. If other applications have implemented this new approach then you run the risk of your shortcuts being hidden from users.

This article has outlined how we can implement the new approach for Sharing Shortcuts within our applications and some of the things to be aware when doing so. Do these changes affect your app, do you have questions about anything mentioned above? Please do reach out with anything that might be on your mind!

Leave a Reply

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