接收来自其他应用的简单数据

正如应用可以向其他应用发送数据一样,它也可以从其他应用接收数据。考虑用户如何与您的应用互动,以及您希望从其他应用接收哪些类型的数据。例如,社交网络应用可能希望从其他应用接收文本内容,例如有趣的网址。

在使用 Compose Navigation 的应用中,接收其他应用发送的数据是一个两步流程:

  1. 在清单中声明 <intent-filter>:您仍必须在 AndroidManifest.xml 文件中为您的 activity 添加 intent 过滤器。这会告知 Android 操作系统您的应用能够接收特定操作(例如 ACTION_SEND)和 MIME 类型(例如 text/plain)。

  2. 在 Compose 导航图中定义 navDeepLink:无需在 activity 的 onCreate 或 onNewIntent 方法中手动拦截和解析 intent,而是使用 Compose Navigation 的深层链接支持。将与操作和 MIME 类型直接匹配的 navDeepLink 附加到应显示内容的可组合目标。NavController 会自动拦截该 intent,并将用户直接路由到相应界面。

Direct Share 目标是指指向应用内特定 Activity 的深层链接。它们通常代表个人或群组,并且 Android Sharesheet 会显示它们。例如,即时通讯应用可以为某个人提供直接分享目标,该目标会直接深层链接到与该人的对话。如需查看详细说明,请参阅提供直接共享目标。

支持的 MIME 类型

理想情况下,应用必须能够接收尽可能广泛的 MIME 类型。例如,一款旨在发送文字、图片和视频的即时通讯应用最好支持接收 text/*、image/* 和 video/*。以下是 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

请参阅 IANA 的 MIME 媒体类型官方注册表。

创建出色的分享目标

当用户点按与特定 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 类型,或者发送的图片可能非常大。另请注意,请在单独的线程(而非主 [“界面”] 线程)中处理二进制数据。

@Composable
fun SharesheetHandler() {
    val activity = LocalActivity.current
    val intent = activity?.intent

    when (intent?.action) {
        Intent.ACTION_SEND -> {
            if (intent.type == "text/plain") {
                handleSendText(intent) // Handle text being sent
            } else if (intent.type?.startsWith("image/") == true) {
                handleSendImage(intent) // Handle single image being sent
            }
        }

        Intent.ACTION_SEND_MULTIPLE -> {
            if (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 state with the shared text
    }
}

private fun handleSendImage(intent: Intent) {
    val imageUri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUri?.let {
        // Update UI state with the shared image
    }
}

private fun handleSendMultipleImages(intent: Intent) {
    val imageUris =
        IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUris?.let {
        // Update UI state with the shared images
    }
}

在收到数据后更新界面可以像填充 TextField 一样简单,也可以像对图片应用有趣的照片滤镜一样复杂。接下来会发生什么情况取决于您的应用。

分享屏幕截图网址

截取屏幕截图时,您可以分享该屏幕截图和任何关联的网址。 这样可以提供更丰富的用户体验。收到网址时,请务必从 intent 中获取 EXTRA_TEXT 字段,如以下示例所示:

IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
    // Handle the EXTRA_TEXT as well
    val extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT)
    // Update UI state with the shared image and the EXTRA_TEXT if available
}

确保用户能够识别您的应用

在 Android Sharesheet 和 intent 解析器中,您的应用通过其图标和标签来表示。两者都在清单中定义。您可以设置 activity 或 intent 过滤器标签,以提供更多上下文。

自 Android 10(API 级别 29)起,Android Sharesheet 仅使用 application 标记中在清单中设置的图标。Android 会忽略在 intent-filter 和 activity 标记中设置的图标。