Sharing Improvements

Android Q provides a number of new features related to sharing.

Sharing Shortcuts API

The ShareSheet has changed in Android Q. The Direct Share APIs have been replaced with the new Sharing Shortcuts API. The existing Direct Share mechanism will continue to work, but have a lower priority than any apps that use the new API.

Instead of retrieving results reactively on demand, the Sharing Shortcuts API lets apps publish direct share targets in advance. This is how the ShortcutManager works. Since the two APIs are similar, we have expanded the ShortcutInfo API to make using both features easier. With the new API, you can directly assign categories or people to a share target. The share targets persist in the system until the same app updates them or the app is uninstalled.

Sample Code: SharingShortcuts

Publish direct share targets

Currently only dynamic shortcuts are supported for publishing direct share targets. Follow these steps to publish direct share targets using the new API:

  1. Declare share-target elements in an app's XML resource file. For details, see Declare a share target below.
  2. Publish dynamic shortcuts with matching categories to the declared share-targets. Shortcuts can be added, accessed, updated, and removed using the ShortcutManager or ShortcutManagerCompat in AndroidX. Using the compatibility library in AndroidX is the preferred method since it provides backwards compatibility on older Android versions.

The DirectShare API

ShortcutInfo.Builder includes new and enhanced methods that provide additional info about the share target:

setCategories()
This is not a new method, but now categories are also used to filter shortcuts that can handle share intents or actions. See Declare a share target below for details. This field is required for shortcuts that are meant to be used as share targets.
setLongLived()
Specifies whether or not a shortcut is valid when it has been unpublished or made invisible by the app (as a dynamic or pinned shortcut). If a shortcut is long lived, it can be cached by various system services even after if has been unpublished as a dynamic shortcut.
setPerson(), setPersons()

Associates one or more Person objects with the shortcut. This can be used to better understand user behavior across different apps, and to help potential prediction services in the framework provide better suggestions in a ShareSheet. Adding Person info to a shortcut is optional, but strongly recommended if the share target can be associated with a person. Note that som share targets, such as cloud, cannot be associated with a person.

For a typical messaging app, a separate share target (shortcut) should be published for each contact, and the Person field should contain the contact's info. If the target can be associated with multiple people (like a group chat), add multiple Persons to a single share target.

Declare a share target

Share targets must be declared in the app's resource file, similar to static shortcuts definitions. Add share target definitions inside the <shortcuts> root element in the resource file, along with other static shortcut definitions. Each <share-target> element contains information about the shared data type, matching categories, and the target class that will handle the share intent. The XML code looks something like this:

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
  <share-target android:targetClass="com.example.android.sharingshortcuts.SendMessageActivity">
    <data android:mimeType="text/plain" />
    <category android:name="com.example.android.sharingshortcuts.category.TEXT_SHARE_TARGET" />
  </share-target>
</shortcuts>

The data element in a share target is similar to the data specification in an intent filter. Each share target can have multiple categories, which are only used to match an app's published shortcuts with its share target definitions. Categories can have any arbitrary app-defined values.

In case the user selects a direct share target (shortcut) in ShareSheet that matches with the example target-share above, the app will get the following share intent:

Action: Intent.ACTION_SEND
ComponentName: {com.example.android.sharingshortcuts /
                com.example.android.sharingshortcuts.SendMessageActivity}
Data: Uri to the shared content
EXTRA_SHORTCUT_ID: <ID of the selected shortcut>

If the user opens the share target from the launcher shortcuts, the app will get the intent that was created when adding the sharing shortcut to the ShortcutManagerCompat. Since it's a different intent, Intent.EXTRA_SHORTCUT_ID won't be available, and you will have to pass the ID manually if you need it.

DirectShare in AndroidX

ShortcutManagerCompat is a new AndroidX API that provides backwards compatibility with the old DirectShare API. This is the preferred way to publish share targets.

To be able to work with the compatibility library, the app’s manifest must contain the meta-data chooser-target-service and intent-filters set. See the current Direct Share API.

This service is already declared in the compatibility library, so the user does not need to declare the service in the app’s manifest. However, the link from the share activity to the service must be taken into account as a chooser target provider.

In the following example, the implementation of ChooserTargetService is androidx.core.content.pm.ChooserTargetServiceCompat, which is already defined in AndroidX:

<activity
    android:name=".SendMessageActivity"
    android:label="@string/app_name"
    android:theme="@style/SharingShortcutsDialogTheme">
    <!-- This activity can respond to Intents of type SEND -->
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <!-- Only needed if you import the sharetarget AndroidX library that
         provides backwards compatibility with the old DirectShare API.
         The activity that receives the Sharing Shortcut intent needs to be
         taken into account with this chooser target provider. -->
    <meta-data
        android:name="android.service.chooser.chooser_target_service"
        android:value="androidx.sharetarget.ChooserTargetServiceCompat" />
</activity>

FAQ

What are the main differences between the new API and the old DirectShare API?

The new API uses a push model, versus the pull model used in the old DirectShare API. This makes the process of retrieving direct share targets much faster when preparing the ShareSheet. From the app developer's point of view, when using the new API, the app needs to provide the list of direct share targets ahead of time, and potentially update the list of shortcuts every time the internal state of the app changes (for example, if a new contact is added in a messaging app).

What happens if I don't migrate to use the new APIs?

On Android Q and higher, ShareSheet will put higher priority on share targets which are provided via ShortcutManager (the new API). So your published share targets may get buried under other apps' share targets and potentially never appear when sharing.

Can I use both old and new DirectShare APIs in my app for backwards compatibility?

Don't do it! Instead, use the provided support library APIs (ShortcutManagerCompat). Mixing the two sets of APIs may result in unwanted/unexpected behavior when retrieving the share targets.

How are published shortcuts for share targets different from launcher shortcuts (the typical usage of shortcuts when long pressing on app icons in launcher)?

Any shortcuts published for a "share target" purpose, is also a launcher shortcut, and will be shown in the menu when long pressing your app's icon. The maximum shortcut count limit per activity also applies to the total number of shortcuts an app is publishing (share targets and legacy launcher shortcuts combined).