提供直接共享目标

图 1:共享表单中的直接共享行,如 1 所示

使用直接共享目标可以更轻松、更快速地让其他应用的用户与您的应用共享 URL、图像或其他类型的数据。直接共享的工作原理是直接在 Android 共享表单上显示来自消息和社交应用的联系人,而无需用户选择应用然后搜索联系人。

ShortcutManagerCompat 是一个提供共享快捷方式的 AndroidX API,并且与已弃用的 ChooserTargetService API 向后兼容。这是发布共享快捷方式和 ChooserTargets 的首选方法。有关说明,请参阅本页上的使用 AndroidX 提供共享快捷方式和 ChooserTargets

发布直接共享目标

共享表单直接共享行仅显示共享快捷方式 API 提供的动态快捷方式。请完成以下步骤以发布直接共享目标。

  1. 在应用的 XML 资源文件中,声明 share-target 元素。

    <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>
    
  2. 当您的应用初始化时,使用 setDynamicShortcuts 按重要性对动态快捷方式进行排序。

    索引越小,重要性越高。如果您正在开发通信应用,则可以按最近使用时间对主要对话进行排序,就像它们在应用中显示的那样。不要发布过时的快捷方式;在过去 30 天内没有用户活动的对话被视为过时。

    Kotlin

    ShortcutManagerCompat.setDynamicShortcuts(myContext, listOf(shortcut1, shortcut2, ..))
    

    Java

    List<ShortcutInfoCompat> shortcuts = new ArrayList<>();
    shortcuts.add(shortcut1);
    shortcuts.add(shortcut2);
    ...
    ShortcutManagerCompat.setDynamicShortcuts(myContext, shortcuts);
    
    
  3. 如果您正在开发通信应用,请通过 pushDynamicShortcut 在用户每次向联系人发送或接收消息时立即报告快捷方式的使用情况。有关更多信息,请参阅本页上的报告通信应用的快捷方式使用情况。例如,通过 ShortcutInfoCompat.Builder#addCapabilityBinding 使用 actions.intent.SEND_MESSAGE 功能在快捷方式中指定功能绑定来报告用户发送的消息的使用情况。

    Kotlin

    val shortcutInfo = ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
      ...
      .setShortLabel(firstName)
      .setLongLabel(fullName)
      .setCategories(matchedCategories)
      .setLongLived(true)
    .addCapabilityBinding("actions.intent.SEND_MESSAGE").build()
    ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo)
    

    Java

    ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
      ...
      .setShortLabel(firstName)
      .setLongLabel(fullName)
      .setCategories(matchedCategories)
      .setLongLived(true)
      .addCapabilityBinding("actions.intent.SEND_MESSAGE")
      .build();
    
    ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo);
    
  4. 如果用户删除了联系人,请使用 removeLongLivedShortcut。无论系统服务是否缓存了快捷方式,这都是删除快捷方式的首选方法。以下代码片段显示了如何执行此操作的示例。

    Kotlin

    val deleteShortcutId = "..."
    ShortcutManagerCompat.removeLongLivedShortcuts(myContext, listOf(deleteShortcutId))
    

    Java

    String deleteShortcutId = "...";
    ShortcutManagerCompat.removeLongLivedShortcuts(
        myContext, Arrays.asList(deleteShortcutId));
    
    

提高直接共享目标的排名

Android 分享表显示固定数量的直接分享目标。这些建议按排名排序。您可以通过执行以下操作来潜在地提高快捷方式的排名

  • 确保所有shortcutIds都是唯一的,并且永远不会重复用于不同的目标。
  • 通过调用setLongLived(true)确保快捷方式是长期存在的。
  • 对于与对话相关的快捷方式,请通过ShortcutManagerCompat.pushDynamicShortcut重新发布相应的快捷方式,以报告传出和传入消息的快捷方式使用情况。有关详细信息,请参阅本页上的报告通信应用的快捷方式使用情况
  • 避免提供不相关或过时的直接分享目标,例如用户在过去 30 天内未发送过消息的联系人。
  • 对于短信应用,避免提供短代码或被识别为潜在垃圾邮件的对话的快捷方式。用户极不可能与这些对话共享内容。
  • 调用setCategories()将快捷方式与相应的mimeType属性相关联。例如,对于短信应用,如果联系人未启用 RCS 或 MMS,则不会将相应的快捷方式与非文本 MIME 类型(例如image/*video/*)相关联。
  • 对于给定的对话,一旦推送动态快捷方式并报告使用情况,请不要更改快捷方式 ID。这确保了保留用于排名的使用数据。

如果用户点击任何直接分享目标,您的应用必须将他们带到一个 UI,以便他们可以直接对目标主题执行操作。不要向用户呈现歧义 UI,也不要将他们放置在与点击的目标无关的 UI 中。例如,在消息应用中,点击直接分享目标会将用户带到与他们选择的联系人进行对话的视图。键盘可见,并且消息已预先填充共享数据。

共享快捷方式 API

从 Android 10(API 级别 29)开始,ShortcutInfo.Builder添加了提供有关共享目标的其他信息的方法和增强功能

setCategories()
从 Android 10 开始,类别也用于过滤可以处理共享意图或操作的快捷方式。有关详细信息,请参阅声明共享目标。对于旨在用作共享目标的快捷方式,此字段是必需的。
setLongLived()

指定快捷方式在应用取消发布或将其设为不可见(作为动态或固定快捷方式)时是否有效。如果快捷方式是长期存在的,即使它已被取消发布为动态快捷方式,它也可以被各种系统服务缓存。

使快捷方式长期存在可以提高其排名。有关详细信息,请参阅获得最佳排名

setShortLabel()setLongLabel()

在将快捷方式发布到个人时,请在setLongLabel()中包含他们的全名,并在setShortLabel()中包含任何简称,例如昵称或名字。

查看在 GitHub 上发布共享快捷方式的示例。

提供快捷方式图像

要创建共享快捷方式,您需要通过setIcon()添加图像。

共享快捷方式可能会出现在整个系统界面中,并且可能会被重新塑造。此外,一些运行 Android 版本 7、8 或 9(API 级别 25、26、27 和 28)的设备可能会显示没有背景的仅位图图标,这会大大降低对比度。为了确保您的快捷方式按预期显示,请使用IconCompat.createWithAdaptiveBitmap()提供自适应位图。

确保自适应位图遵循为自适应图标设置的相同指南和尺寸。实现此目的最常见的方法是将目标正方形位图缩放至 72x72 dp,并将其居中在 108x108 dp 的透明画布中。如果您的图标包含透明区域,则需要包含背景颜色;否则,透明区域将显示为黑色。

不要提供遮罩到特定形状的图像。例如,在 Android 10(API 级别 29)之前,通常为直接共享ChooserTarget提供遮罩到圆形的用户头像。Android 10 中的 Android 分享表和其他系统界面现在可以塑造和主题化快捷方式图像。通过ShortcutManagerCompat提供共享快捷方式的首选方法会自动将后向兼容的直接共享ChooserTarget对象塑造成圆形。

声明共享目标

共享目标必须在应用的资源文件中声明,类似于静态快捷方式定义。将共享目标定义添加到资源文件中的<shortcuts>根元素内,以及其他静态快捷方式定义。每个<share-targets>元素包含有关共享数据类型、匹配类别以及将处理共享意图的目标类的信息。XML 代码如下所示

<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>

共享目标中的 data 元素类似于意图过滤器中的数据规范。每个共享目标可以有多个类别,这些类别仅用于将应用发布的快捷方式与其共享目标定义匹配。类别可以具有任何任意应用定义的值。

如果用户在 Android 分享表中选择与上述示例 target-share 匹配的共享快捷方式,则应用将获得以下共享意图

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>

如果用户从启动器快捷方式打开共享目标,则应用将获得在将共享快捷方式添加到ShortcutManagerCompat时创建的意图。由于它是一个不同的意图,因此Intent.EXTRA_SHORTCUT_ID将不可用,如果需要,您将不得不手动传递 ID。

报告通信应用的快捷方式使用情况

如果您正在开发通信应用,则可以通过报告传出和传入消息的使用情况来提高您在 Android 分享表中的排名。为此,请通过ShortcutManagerCompat.pushDynamicShortcut重新发布代表联系人的对话快捷方式。

快捷方式使用情况和功能绑定向后兼容到 Android 5.0(API 21)。

报告传出消息的快捷方式使用情况

报告用户发送的消息的使用情况在功能上类似于在创建消息后点击“发送”按钮。

要触发使用情况报告,请通过ShortcutInfoCompat.Builder#addCapabilityBinding使用actions.intent.SEND_MESSAGE功能在快捷方式中指定功能绑定。

Kotlin

val shortcutInfo = ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
  ...
  .setShortLabel(firstName)
  .setLongLabel(fullName)
  .setCategories(matchedCategories)
  .setLongLived(true)
.addCapabilityBinding("actions.intent.SEND_MESSAGE").build()
ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo)

Java

ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
  ...
  .setShortLabel(firstName)
  .setLongLabel(fullName)
  .setCategories(matchedCategories)
  .setLongLived(true)
  .addCapabilityBinding("actions.intent.SEND_MESSAGE")
  .build();

ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo);

如果传出消息是针对群聊,则还必须添加Audience参数值,因为recipient类型与功能相关联。

Kotlin

val shortcutInfo = ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
  ...
  .setShortLabel(groupShortTitle)
  .setLongLabel(groupLongTitle)
  .setCategories(matchedCategories)
  .setLongLived(true)
  .addCapabilityBinding("actions.intent.SEND_MESSAGE", "message.recipient.@type", listOf("Audience")).build()

ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo)

Java

ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
  ...
  .setShortLabel(groupShortTitle)
  .setLongLabel(groupLongTitle)
  .setCategories(matchedCategories)
  .setLongLived(true)
  .addCapabilityBinding("actions.intent.SEND_MESSAGE", "message.recipient.@type", Arrays.asList("Audience"))
  .build();

ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo);

报告传入消息的快捷方式使用情况

要触发用户收到短信、聊天消息、电子邮件或通知等消息时的使用情况报告,还必须通过ShortcutInfoCompat.Builder#addCapabilityBinding使用actions.intent.RECEIVE_MESSAGE功能在快捷方式中指定功能绑定。

Kotlin

val shortcutInfo = ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
  ...
  .setShortLabel(firstName)
  .setLongLabel(fullName)
  .setCategories(matchedCategories)
  .setLongLived(true)
  .addCapabilityBinding("actions.intent.RECEIVE_MESSAGE").build()

ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo)

Java

ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
  ...
  .setShortLabel(firstName)
  .setLongLabel(fullName)
  .setCategories(matchedCategories)
  .setLongLived(true)
  .addCapabilityBinding("actions.intent.RECEIVE_MESSAGE")
  .build();

ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo);

如果传入消息来自群聊,则还必须添加Audience参数值,因为sender类型与功能相关联。

Kotlin

val shortcutInfo = ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
  ...
  .setShortLabel(groupShortTitle)
  .setLongLabel(groupLongTitle)
  .setCategories(matchedCategories)
  .setLongLived(true)
  .addCapabilityBinding("actions.intent.RECEIVE_MESSAGE", "message.sender.@type", listOf("Audience")).build()

ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo)

Java

ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(myContext, staticConversationIdentifier)
  ...
  .setShortLabel(groupShortTitle)
  .setLongLabel(groupLongTitle)
  .setCategories(matchedCategories)
  .setLongLived(true)
  .addCapabilityBinding("actions.intent.RECEIVE_MESSAGE", "message.sender.@type", Arrays.asList("Audience"))
  .build();

ShortcutManagerCompat.pushDynamicShortcut(myContext, shortcutInfo);

使用 AndroidX 提供共享快捷方式和 ChooserTargets

为了能够使用 AndroidX 兼容库,应用的清单必须包含元数据 chooser-target-service 和 intent-filters 设置。请参阅当前的ChooserTargetService直接分享 API。

此服务已在兼容库中声明,因此用户无需在应用的清单中声明此服务。但是,必须将从共享活动到服务的链接考虑为选择器目标提供程序。

在以下示例中,ChooserTargetService的实现是androidx.core.content.pm.ChooserTargetServiceCompat,它已在 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>

共享快捷方式常见问题解答

快捷方式使用数据如何存储以及它们是否会离开设备?

快捷方式完全存储在设备上的系统数据目录中的加密磁盘分区中。快捷方式中的信息(例如图标、意图以及人员和资源的名称)仅供系统服务和发布快捷方式的同一应用访问。

直接分享的历史是什么?

我们在 Android 6.0(API 级别 23)中引入了直接分享,以允许应用通过ChooserTargetService提供ChooserTarget对象。结果是按需被动检索的,导致目标加载时间缓慢。

在 Android 10(API 级别 29)中,我们用新的共享快捷方式 API 替换了ChooserTargetService直接分享 API。共享快捷方式 API 允许应用预先发布直接分享目标,而不是按需被动检索结果。这加快了准备 ShareSheet 时检索直接分享目标的过程。ChooserTargetService直接分享机制将继续工作,但系统会将通过这种方式提供的目标的排名低于使用共享快捷方式 API 的任何目标。

Android 11(API 级别 30)弃用了ChooserTargetService服务,共享快捷方式 API 是提供直接分享目标的唯一方法。

发布的共享目标快捷方式与启动器快捷方式(在启动器中长按应用图标时快捷方式的典型用法)有何不同?

任何发布用于“共享目标”目的的快捷方式,也都是启动器快捷方式,并且在长按应用图标时会显示在菜单中。每个活动的快捷方式最大数量限制也适用于应用发布的快捷方式总数(共享目标和传统启动器快捷方式的组合)。

关于应发布多少个共享快捷方式的指导是什么?

共享快捷方式的数量受限于通过getMaxShortcutCountPerActivity(android.content.Context)提供的动态快捷方式的相同限制。可以发布任何数量的快捷方式以达到该限制,但必须记住,共享快捷方式可以在应用启动器长按菜单和分享表中可见。大多数应用启动器在长按时在纵向模式下最多显示四个或五个快捷方式,在横向模式下最多显示八个快捷方式。有关共享快捷方式的更多详细信息和指南,请参阅此常见问题解答