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

Android 使用 Intent 及其关联的 extra 来让用户使用其喜爱的应用快速轻松地共享信息。

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

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

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

为何使用 Android 分享表

我们强烈建议您使用 Android 分享表,以在应用之间为用户创建一致性。不要显示您应用自己的共享目标列表,也不要创建您自己的分享表变体。

Android 分享表让用户只需轻触一下,即可将信息分享给正确的人,并提供相关的应用建议。分享表可以建议自定义解决方案无法提供的目标,并采用一致的排名。这是因为分享表可以考虑仅系统可用的应用和用户活动信息。

Android 分享表还为开发者提供了许多便捷功能。例如,您可以执行以下操作:

使用 Android 分享表

对于所有类型的共享,请创建一个 Intent 并将其 action 设置为 Intent.ACTION_SEND。要显示 Android 分享表,请调用 Intent.createChooser(),并传入您的 Intent 对象。它会返回一个始终显示 Android 分享表的 Intent 版本。

发送文本内容

Android 分享表最直接和常见的用途是将文本内容从一个 Activity 发送到另一个 Activity。例如,大多数浏览器可以将当前显示页面的 URL 作为文本共享给另一个应用。这对于通过电子邮件或社交网络与朋友分享文章或网站非常有用。下面是实现此目的的示例:

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)期望 EXTRA_EMAILEXTRA_CC 等 extra 为 String[] 类型。使用 putExtra(String, String[]) 将这些添加到您的 Intent。

发送二进制内容

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

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 level 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 类型的更多信息,请参阅 IANA 官方 MIME 媒体类型注册表。

Android 分享表可能会显示内容预览,具体取决于所提供的 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 level 29) 开始,Android 分享表会显示共享文本的预览。在某些情况下,共享的文本可能难以理解。考虑共享一个复杂的 URL,例如 https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4。更丰富的预览可以向用户保证正在共享的内容。

如果您正在预览文本,可以设置标题、缩略图或两者。在调用 Intent.createChooser() 之前将描述添加到 Intent.EXTRA_TITLE,并使用 ClipData 添加相关的缩略图。

注意:图像内容 URI 由 FileProvider 提供,通常来自配置的 <cache-path>。有关更多信息,请参阅共享文件。请务必授予分享表读取您想用作缩略图的任何图像的正确权限。有关更多信息,请参code translate="no" dir="ltr">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));

预览效果大致如下:

为分享表添加自定义操作

Android 分享表上自定义操作的屏幕截图。

在 Android 14 (API Level 34) 及更高版本上,应用可以将自定义操作添加到 Android 分享表。自定义操作以小操作图标的形式显示在 Android 分享表的顶部,应用可以指定任何 Intent 作为点击图标时调用的操作。

要在 Android 分享表上添加自定义操作,首先使用 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 分享表允许您指定最多两个 ChooserTarget 对象,这些对象显示在共享快捷方式和从 ChooserTargetServices 加载的 chooser 目标之前。您还可以指定最多两个指向 Activity 的 Intent,这些 Activity 列在应用建议之前:

在调用 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.EXTRA_EXCLUDE_COMPONENTS 添加到您的 Intent。

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 分享表允许您通过提供用户使用 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);
}

为分享表添加自定义操作

在 Android 14 (API Level 34) 及更高版本上,应用可以将自定义操作添加到 Android 分享表。使用 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 分享表一样。但是,不要调用 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 过滤器。