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 可以考虑到只有系统了解的应用和用户 activity 的相关信息。
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_EMAIL
、EXTRA_CC
、EXTRA_BCC
)、电子邮件主题 (EXTRA_SUBJECT
) 等。
注意:某些电子邮件应用(如 Gmail)要求以 String[]
的形式表示诸如 EXTRA_EMAIL
和 EXTRA_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
辅助程序类。 - 使用系统
MediaStore
。MediaStore
主要用于存储视频、音频和图片 MIME 类型的数据。不过,从 Android 3.0(API 级别 11)开始,它也可以存储非媒体类型的数据。如需了解详情,请参阅MediaStore.Files
。可以使用scanFile()
将文件插入MediaStore
,然后将适合分享的content://
样式Uri
传递给提供的onScanCompleted()
回调。请注意,将内容添加到系统MediaStore
后,设备上的任何应用均可访问该内容。
使用正确的 MIME 类型
为要发送的数据提供最具体的 MIME 类型。例如,分享纯文本时,应使用 text/plain
。以下是在 Android 中发送简单数据时一些常用的 MIME 类型:
接收器注册 | 发件人发送 |
---|---|
text/* |
|
`image/*` |
|
video/* |
|
支持的文件扩展名 | 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 14(API 级别 34)及更高版本中,应用可以向 Android Sharesheet 添加自定义操作。自定义操作会显示为 Android Sharesheet 顶部的操作小图标,应用可以将任何 Intent
指定为点击该图标时调用的操作。
如需在 Android Sharesheet 中添加自定义操作,请先使用 ChooserAction.Builder
创建 ChooserAction
。您可以指定 PendingIntent
作为点击该图标时调用的操作。创建一个包含所有自定义操作的数组,并将其指定为分享 Intent
的 EXTRA_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,您最多可以指定两个 ChooserTarget
对象,在分享快捷方式和通过 ChooserTargetServices
加载的 ChooserTarget 之前显示。此外,您还可以指定最多两个指向在应用建议之前列出的 activity 的 intent:
调用 Intent.createChooser()
之后,将 Intent.EXTRA_CHOOSER_TARGETS
和 Intent.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);
请谨慎使用此功能。每添加一个自定义 Intent
和 ChooserTarget
,系统推荐的次数就会相应地减少。我们通常不建议添加自定义目标。添加 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 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
作为点击该图标时调用的操作。创建一个包含所有自定义操作的数组,并将其指定为分享 Intent
的 EXTRA_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 解析器
在明确定义的任务流中将数据发送到另一个应用时,使用 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 过滤器。