就像应用可以向其他应用发送数据一样,它也可以从其他应用接收数据。考虑用户如何与您的应用互动,以及您希望从其他应用接收哪些类型的数据。例如,社交网络应用可能希望从其他应用接收文本内容,例如有趣的网址。
其他应用的用户经常通过 Android Sharesheet 或 intent 解析器向您的应用发送数据。向您的应用发送数据的应用必须为该数据设置 MIME 类型。您的应用可以通过以下方式接收其他应用发送的数据:
- 在清单中有匹配的
intent-filter
标记的Activity
- 您的应用发布的共享快捷方式。
直接共享目标是指向您应用中特定 activity 的深层链接。它们通常代表个人或群组,Android Sharesheet 会显示它们。例如,即时通讯应用可以提供直接共享目标,以便用户直接深入与该用户的对话。如需了解详细说明,请参阅提供直接共享目标。
支持 MIME 类型
理想情况下,应用必须能够接收尽可能广泛的 MIME 类型。例如,用于发送短信、图片和视频的即时通讯应用最好支持接收 text/*
、image/*
和 video/*
。以下是在 Android 中用于发送和接收简单数据的一些常见 MIME 类型。
接收方注册 | 发件人发送 |
---|---|
text/* |
|
`image/*` |
|
video/* |
|
支持的文件扩展名 | application/pdf |
请参阅 MIME 媒体类型的 IANA 官方注册表。
设置出色的共享目标
当用户点按与特定 activity 关联的共享目标时,他们应该能够在使用共享内容之前确认和修改共享内容。这对于文本数据尤其重要。
通过 activity 接收数据
通过 activity 接收数据涉及更新清单、处理传入的内容,以及确保用户识别您的应用。
更新您的清单
intent 过滤器会告知系统应用组件接受哪些 intent。与向其他应用发送简单数据一课中您使用 ACTION_SEND
操作构建 intent 的方法类似,您也创建 intent 过滤器,以通过此操作接收 intent。您可以使用 <intent-filter>
元素在清单中定义 intent 过滤器。例如,如果您的应用会处理文本内容的接收,则包含一个或多个任意类型图片的清单将如以下代码段所示:
<activity android:name=".ui.MyActivity" > <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.SEND_MULTIPLE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-filter> </activity>
当其他应用尝试通过构建 intent 并将其传递给 startActivity()
来分享任何这些内容时,您的应用会在 Android Sharesheet 或 intent 解析器中列为一个选项。如果用户选择您的应用,这将启动相应的 activity(上例中的 .ui.MyActivity
)。然后,您需要在代码和界面中对内容进行适当处理。
处理传入的内容
如需处理 Intent
传送的内容,请调用 getIntent()
以获取 Intent
对象。获得对象后,您可以检查其内容以确定下一步操作。如果此 activity 可以从系统的其他部分(例如启动器)启动,请在检查 intent 时考虑到这一点。
请格外小心检查传入的数据,因为您永远不知道其他应用可能会向您发送什么。例如,可能设置了错误的 MIME 类型,或者正在发送的图片可能非常大。此外,请记得在单独的线程而不是主(“界面”)线程中处理二进制数据。
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... when { intent?.action == Intent.ACTION_SEND -> { if ("text/plain" == intent.type) { handleSendText(intent) // Handle text being sent } else if (intent.type?.startsWith("image/") == true) { handleSendImage(intent) // Handle single image being sent } } intent?.action == Intent.ACTION_SEND_MULTIPLE && intent.type?.startsWith("image/") == true -> { handleSendMultipleImages(intent) // Handle multiple images being sent } else -> { // Handle other intents, such as being started from the home screen } } ... } private fun handleSendText(intent: Intent) { intent.getStringExtra(Intent.EXTRA_TEXT)?.let { // Update UI to reflect text being shared } } private fun handleSendImage(intent: Intent) { (intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let { // Update UI to reflect image being shared } } private fun handleSendMultipleImages(intent: Intent) { intent.getParcelableArrayListExtra<Parcelable>(Intent.EXTRA_STREAM)?.let { // Update UI to reflect multiple images being shared } }
Java
void onCreate (Bundle savedInstanceState) { ... // Get intent, action and MIME type Intent intent = getIntent(); String action = intent.getAction(); String type = intent.getType(); if (Intent.ACTION_SEND.equals(action) && type != null) { if ("text/plain".equals(type)) { handleSendText(intent); // Handle text being sent } else if (type.startsWith("image/")) { handleSendImage(intent); // Handle single image being sent } } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) { if (type.startsWith("image/")) { handleSendMultipleImages(intent); // Handle multiple images being sent } } else { // Handle other intents, such as being started from the home screen } ... } void handleSendText(Intent intent) { String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); if (sharedText != null) { // Update UI to reflect text being shared } } void handleSendImage(Intent intent) { Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); if (imageUri != null) { // Update UI to reflect image being shared } } void handleSendMultipleImages(Intent intent) { ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); if (imageUris != null) { // Update UI to reflect multiple images being shared } }
收到数据后更新界面的操作可能很简单(比如只需填充 EditText
),也可能比较复杂(比如需要将有趣的照片滤镜应用到图片)。接下来执行什么操作将由您的应用决定。
确保用户能够识别您的应用
在 Android Sharesheet 和 intent 解析器中,您的应用由其图标和标签表示。两者都在清单中定义。您可以设置 activity 或 intent 过滤器标签以提供更多上下文。
从 Android 10(API 级别 29)开始,Android Sharesheet 将仅使用清单中的 application
标记中设置的图标。Android 会忽略在 intent-filter
和 activity
标记上设置的图标。