提供直接共享目标

图 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#addCapabilityBindingactions.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)之前,通常为 Direct Share ChooserTarget提供用户头像,这些头像被遮罩成圆形。Android 10 中的 Android 共享表单和其他系统界面现在会塑造和主题化快捷方式图像。通过ShortcutManagerCompat提供共享快捷方式的首选方法会自动将后向兼容 Direct Share 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 共享表单中选择与上面示例目标共享匹配的共享快捷方式,则应用将获得以下共享意图

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 设置。请参阅当前的ChooserTargetServiceDirect Share 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>

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

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

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

Direct Share 的历史是什么?

我们在 Android 6.0(API 级别 23)中引入了 Direct Share,以允许应用通过ChooserTargetService提供ChooserTarget对象。结果是根据需要以反应式方式检索的,导致目标加载时间缓慢。

在 Android 10(API 级别 29)中,我们用新的共享快捷方式 API 替换了ChooserTargetService Direct Share API。共享快捷方式 API 不再根据需要以反应式方式检索结果,而是允许应用提前发布 Direct Share 目标。这极大地加快了在准备共享表单时检索 Direct Share 目标的过程。ChooserTargetService Direct Share 机制将继续工作,但系统会将通过这种方式提供的目标的排名低于使用共享快捷方式 API 的任何目标。

Android 11(API 级别 30)已弃用ChooserTargetService服务,并且共享快捷方式 API 是提供 Direct Share 目标的唯一方法。

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

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

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

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