将简单的数据发送到其他应用

Android 使用 intent 及其关联的 extra 来让用户使用他们喜欢的应用快速轻松地分享信息。

Android 为用户提供了两种在应用之间分享数据的方式:

  • Android Sharesheet 主要用于将内容发送到您的应用外部和/或直接发送给其他用户。例如,将网址分享给朋友。
  • Android intent 解析器最适合将数据传递到明确定义的任务的下一阶段。例如,从应用中打开 PDF,并让用户选择他们首选的查看器。

构造 intent 时,您可以指定希望该 intent 执行的操作。Android 使用 ACTION_SEND 操作将数据从一个 activity 发送到另一个 activity,即使跨越进程边界也是如此。您需要指定数据及其类型。系统会自动识别可以接收数据的兼容 activity 并将其显示给用户。对于 intent 解析器,如果只有一个 activity 可以处理 intent,该 activity 会立即启动。

为什么要使用 Android Sharesheet

我们强烈建议您使用 Android Sharesheet 在各个应用中为用户提供一致的数据。不要显示应用自己的共享目标列表,也不要创建自己的 Sharesheet 变体。

借助 Android Sharesheet,用户只需点按一下,即可通过相关的应用建议与合适的人员分享信息。Sharesheet 可以建议自定义解决方案不可用的目标,并使用一致的排名。这是因为 Sharesheet 可以考虑到只有系统可用的应用和用户活动信息。

Android Sharesheet 还为开发者提供了许多方便的功能。例如,您可以执行以下操作:

使用 Android Sharesheet

对于所有类型的共享,请创建一个 intent,并将其操作设置为 Intent.ACTION_SEND。如需显示 Android Sharesheet,请调用 Intent.createChooser(),并向其传递您的 Intent 对象。它会返回一个 intent 版本,该版本始终显示 Android Sharesheet。

发送文字内容

Android Sharesheet 最直接且最常见的用途是将文本内容从一个 activity 发送到另一个 activity。例如,大多数浏览器都能以文本形式与另一个应用分享当前显示的网页的网址。这对于通过电子邮件或社交网络与朋友分享文章或网站非常有用。下面举例说明如何执行此操作:

Kotlin

val sendIntent: Intent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
    type = "text/plain"
}

val shareIntent = Intent.createChooser(sendIntent, null)
startActivity(shareIntent)

Java

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");

Intent shareIntent = Intent.createChooser(sendIntent, null);
startActivity(shareIntent);

或者,您可以添加 extra 以包含更多信息,例如电子邮件收件人(EXTRA_EMAILEXTRA_CCEXTRA_BCC)、电子邮件主题 (EXTRA_SUBJECT) 等。

注意:某些电子邮件应用(如 Gmail)需要 String[] 才能提供 EXTRA_EMAILEXTRA_CC 等 extra。使用 putExtra(String, String[]) 将它们添加到您的 intent 中。

发送二进制内容

您可以使用 ACTION_SEND 操作共享二进制数据。请设置适当的 MIME 类型,并在 extra EXTRA_STREAM 中放置数据的 URI,如以下示例所示。这通常用于分享图片,但可用于分享任何类型的二进制内容。

Kotlin

val shareIntent: Intent = Intent().apply {
    action = Intent.ACTION_SEND
    // Example: content://com.google.android.apps.photos.contentprovider/...
    putExtra(Intent.EXTRA_STREAM, uriToImage)
    type = "image/jpeg"
}
startActivity(Intent.createChooser(shareIntent, null))

Java

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
// Example: content://com.google.android.apps.photos.contentprovider/...
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, null));

接收应用需要获得相应权限才能访问 Uri 指向的数据。您可以通过以下两种方式执行此操作:

  • 将数据存储在您自己的 ContentProvider 中,确保其他应用具有访问您的提供程序的正确权限。提供访问权限的首选机制是使用“按 URI 的权限”,这种权限是临时的,并且仅向接收应用授予访问权限。创建这样的 ContentProvider 的一种简单方法是使用 FileProvider 辅助类。
  • 使用系统 MediaStoreMediaStore 主要用于视频、音频和图片 MIME 类型。不过,从 Android 3.0(API 级别 11)开始,它还可以存储非媒体类型。如需了解详情,请参阅 MediaStore.Files。 您可以使用 scanFile() 将文件插入 MediaStore,之后会将适合共享的 content:// 样式 Uri 传递给提供的 onScanCompleted() 回调。请注意,将内容添加到系统 MediaStore 后,设备上的任何应用均可访问这些内容。

使用正确的 MIME 类型

为您要发送的数据提供可用的最具体的 MIME 类型。例如,分享纯文本时使用 text/plain。以下是在 Android 中发送简单数据时常见的一些 MIME 类型:

接收方注册 发件人发送
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
`image/*`
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
支持的文件扩展名 application/pdf

如需详细了解 MIME 类型,请参阅 MIME 媒体类型的 IANA 官方注册表。

Android Sharesheet 可能会显示内容预览,具体取决于提供的 MIME 类型。某些预览功能仅适用于特定类型。

分享多份内容

如需分享多份内容,请将 ACTION_SEND_MULTIPLE 操作与指向相应内容的 URI 列表结合使用。MIME 类型因您要共享的内容组合而异。例如,如果您分享三张 JPEG 图片,则应使用 "image/jpg" 类型。如果需要混合使用多种图片类型,请使用 "image/*" 来匹配处理任何类型的图片的 activity。虽然可以共享多种类型,但我们强烈建议不要这样做,因为接收方不清楚应该发送什么内容。如果需要发送多种类型的数据,请使用 "*/*"。由接收应用解析和处理您的数据。示例如下:

Kotlin

val imageUris: ArrayList<Uri> = arrayListOf(
        // Add your image URIs here
        imageUri1,
        imageUri2
)

val shareIntent = Intent().apply {
    action = Intent.ACTION_SEND_MULTIPLE
    putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris)
    type = "image/*"
}
startActivity(Intent.createChooser(shareIntent, null))

Java

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
imageUris.add(imageUri2);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, null));

请确保提供的 Uri 对象指向接收应用可以访问的数据。

向文本预览添加富媒体内容

从 Android 10(API 级别 29)开始,Android Sharesheet 可以显示分享的文本的预览。在某些情况下,分享的文本可能难以理解。建议分享一个复杂的网址,例如 https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4。预览内容更丰富可以让用户感到放心,让他们知道分享的内容。

如需预览文本,您可以设置标题和/或缩略图。在调用 Intent.createChooser() 之前,为 Intent.EXTRA_TITLE 添加说明,并使用 ClipData 添加相关的缩略图。

注意:图片内容 URI 通过 FileProvider(通常来自配置的 <cache-path>)提供。如需了解详情,请参阅分享文件。请务必授予 Sharesheet 适当的权限,以读取您要用作缩略图的所有图片。如需了解详情,请参阅 Intent.FLAG_GRANT_READ_URI_PERMISSION

示例如下:

Kotlin

 val share = Intent.createChooser(Intent().apply {
      action = Intent.ACTION_SEND
      putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/")

      // (Optional) Here you're setting the title of the content
      putExtra(Intent.EXTRA_TITLE, "Introducing content previews")

      // (Optional) Here you're passing a content URI to an image to be displayed
      data = contentUri
      flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
  }, null)
  startActivity(share)

Java

Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/");

// (Optional) Here you're setting the title of the content
sendIntent.putExtra(Intent.EXTRA_TITLE, "Introducing content previews");

// (Optional) Here you're passing a content URI to an image to be displayed
sendIntent.setData(contentUri);
sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

// Show the Sharesheet
startActivity(Intent.createChooser(sendIntent, null));

预览如下所示:

向 Sharesheet 添加自定义操作

Android Sharesheet 上自定义操作的屏幕截图。

在 Android 14(API 级别 34)及更高版本中,应用可以向 Android Sharesheet 添加自定义操作。自定义操作显示为 Android Sharesheet 顶部的小操作图标,并且应用可以将任何 Intent 指定为在用户点击图标时调用的操作。

如需在 Android Sharesheet 上添加自定义操作,请先使用 ChooserAction.Builder 创建一个 ChooserAction。 您可以将 PendingIntent 指定为点击图标时调用的操作。创建一个包含所有自定义操作的数组,并将其指定为共享 IntentEXTRA_CHOOSER_CUSTOM_ACTIONS

Kotlin

val sendIntent = Intent(Intent.ACTION_SEND)
    .setType("text/plain")
    .putExtra(Intent.EXTRA_TEXT, text)
val shareIntent = Intent.createChooser(sendIntent, null)
val customActions = arrayOf(
    ChooserAction.Builder(
        Icon.createWithResource(context, R.drawable.ic_custom_action),
        "Custom",
        PendingIntent.getBroadcast(
            context,
            1,
            Intent(Intent.ACTION_VIEW),
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
        )
    ).build()
)
shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions)
context.startActivity(shareIntent)

Java

Intent sendIntent = new Intent(Intent.ACTION_SEND)
        .setType("text.plain")
        .putExtra(Intent.EXTRA_TEXT, text);
Intent shareIntent = Intent.createChooser(sendIntent, null);
ChooserAction[] actions = new ChooserAction[]{
        new ChooserAction.Builder(
                Icon.createWithResource(context, R.drawable.ic_custom_action),
                "Custom",
                PendingIntent.getBroadcast(
                        context,
                        1,
                        new Intent(Intent.ACTION_VIEW),
                        PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT
                )
        ).build()
};
shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, actions);
context.startActivity(shareIntent);

添加自定义目标

借助 Android Sharesheet,您可以指定最多两个在共享快捷方式和从 ChooserTargetServices 加载的选择器目标之前显示的 ChooserTarget 对象。您还可以指定最多两个指向应用建议前列出的 activity 的 intent:

调用 Intent.createChooser() 之后,将 Intent.EXTRA_CHOOSER_TARGETSIntent.EXTRA_INITIAL_INTENTS 添加到您的共享 intent:

Kotlin

val share = Intent.createChooser(myShareIntent, null).apply {
    putExtra(Intent.EXTRA_CHOOSER_TARGETS, myChooserTargetArray)
    putExtra(Intent.EXTRA_INITIAL_INTENTS, myInitialIntentArray)
}

Java

Intent shareIntent = Intent.createChooser(sendIntent, null);
share.putExtra(Intent.EXTRA_CHOOSER_TARGETS, myChooserTargetArray);
share.putExtra(Intent.EXTRA_INITIAL_INTENTS, myInitialIntentArray);

请谨慎使用此功能。每添加一个自定义 IntentChooserTarget,系统推荐的次数就会相应地减少。我们通常不建议添加自定义目标。添加 Intent.EXTRA_INITIAL_INTENTS 的一个恰当的常见例子是,提供用户可以对共享内容执行的其他操作。例如,如果用户分享图片,系统会使用 Intent.EXTRA_INITIAL_INTENTS 让他们发送链接。添加 Intent.EXTRA_CHOOSER_TARGETS 的一个恰当的常见例子是为了呈现您的应用提供的相关人员或设备。

按组件排除特定目标

您可以通过提供 Intent.EXTRA_EXCLUDE_COMPONENTS 排除特定目标。这样做只是为了移除您可以控制的目标。一个常见的用例是,当用户从应用内分享内容时,隐藏应用的分享目标,因为他们的意图很可能是在应用内分享。

调用 Intent.createChooser() 后,向您的 intent 添加 Intent.EXTRA_EXCLUDE_COMPONENTS

Kotlin

  val share = Intent.createChooser(Intent(), null).apply {
    // Only use for components you have control over
    val excludedComponentNames = arrayOf(ComponentName("com.example.android", "ExampleClass"))
    putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames)
  }

Java

  Intent shareIntent = Intent.createChooser(new Intent(), null);
  // Only use for components you have control over
  ComponentName[] excludedComponentNames = {
          new ComponentName("com.example.android", "ExampleClass")
  };
  shareIntent.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames);

获取有关共享的信息

了解用户何时分享以及他们选择了什么目标可能很有用。借助 Android Sharesheet,您可以使用 IntentSender 提供用户选择的目标的 ComponentName,从而获取此信息。

首先,为 BroadcastReceiver 创建一个 PendingIntent,并在 Intent.createChooser() 中提供其 IntentSender

Kotlin

var share = Intent(Intent.ACTION_SEND)
// ...
val pi = PendingIntent.getBroadcast(
    myContext, requestCode,
    Intent(myContext, MyBroadcastReceiver::class.java),
    PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
share = Intent.createChooser(share, null, pi.intentSender)

Java

Intent share = new Intent(ACTION_SEND);
...
PendingIntent pi = PendingIntent.getBroadcast(myContext, requestCode,
        new Intent(myContext, MyBroadcastReceiver.class),
        PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
share = Intent.createChooser(share, null, pi.getIntentSender());

MyBroadcastReceiver 中接收回调并查看 Intent.EXTRA_CHOSEN_COMPONENT

Kotlin

override fun onReceive(context: Context, intent: Intent) {
  ...
  val clickedComponent : ComponentName = intent.getParcelableExtra(EXTRA_CHOSEN_COMPONENT);
}

Java

@Override public void onReceive(Context context, Intent intent) {
  ...
  ComponentName clickedComponent = intent.getParcelableExtra(EXTRA_CHOSEN_COMPONENT);
}

向 Sharesheet 添加自定义操作

在 Android 14(API 级别 34)及更高版本中,应用可以向 Android Sharesheet 添加自定义操作。使用 ChooserAction.Builder 创建 ChooserAction。您可以将 PendingIntent 指定为点击图标时调用的操作。创建一个包含所有自定义操作的数组,并将其指定为共享 IntentEXTRA_CHOOSER_CUSTOM_ACTIONS

Kotlin

val sendIntent = Intent(Intent.ACTION_SEND)
    .setType("text/plain")
    .putExtra(Intent.EXTRA_TEXT, text)
val shareIntent = Intent.createChooser(sendIntent, null)
val customActions = arrayOf(
    ChooserAction.Builder(
        Icon.createWithResource(context, R.drawable.ic_custom_action),
        "Custom",
        PendingIntent.getBroadcast(
            context,
            1,
            Intent(Intent.ACTION_VIEW),
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
        )
    ).build()
)
shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions)
context.startActivity(shareIntent)

Java

Intent sendIntent = new Intent(Intent.ACTION_SEND)
        .setType("text.plain")
        .putExtra(Intent.EXTRA_TEXT, text);
Intent shareIntent = Intent.createChooser(sendIntent, null);
ChooserAction[] actions = new ChooserAction[]{
        new ChooserAction.Builder(
                Icon.createWithResource(context, R.drawable.ic_custom_action),
                "Custom",
                PendingIntent.getBroadcast(
                        context,
                        1,
                        new Intent(Intent.ACTION_VIEW),
                        PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT
                )
        ).build()
};
shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, actions);
context.startActivity(shareIntent);

使用 Android intent 解析器

ACTION_SEND intent 解析器的屏幕截图。

在明确定义的任务流中将数据发送到另一个应用时,使用 Android intent 解析器最为合适。

如需使用 Android intent 解析器,请创建一个 intent 并添加 extra,就像调用 Android Sharesheet 一样。不过,请勿调用 Intent.createChooser()

如果有多个已安装应用的过滤条件与 ACTION_SEND 和 MIME 类型匹配,系统会显示一个名为“intent 解析器”的消除歧义对话框,用户可通过该对话框选择要分享的目标。如果只有一个应用匹配,它将运行。

下面举例说明如何使用 Android intent 解析器发送文本:

Kotlin

val sendIntent: Intent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
    type = "text/plain"
}
startActivity(sendIntent)

Java

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(sendIntent);

了解详情

如需详细了解如何发送数据,请参阅 intent 和 intent 过滤器