允许其他应用启动您的 activity

如果您的应用可以执行对另一个应用可能有用的操作,您的应用应通过在 activity 中指定适当的 intent 过滤器,准备好响应操作请求。

例如,如果您构建一款可与用户的好友分享消息或照片的社交应用,则应该支持 ACTION_SEND intent。然后,当用户从其他应用发起“分享”操作时,您的应用将在选择器对话框(也称为“消除歧义对话框”)中作为选项显示,如图 1 所示。

图 1. 选择器对话框

如需允许其他应用以此种方式启动您的 activity,您需要在清单文件中为对应的 <activity> 元素添加一个 <intent-filter> 元素。

当您的应用安装在设备上时,系统会识别您的 intent 过滤器,并将信息添加至所有已安装应用所支持的 intent 的内部目录。当应用通过隐式 intent 调用 startActivity()startActivityForResult() 时,系统会找到可响应该 intent 的一个或多个 activity。

添加 intent 过滤器

为正确定义您的 activity 可以处理哪些 intent,您添加的每个 intent 过滤器在 activity 接受的操作类型和数据类型方面应尽可能具体。

如果 activity 具有满足以下 Intent 对象条件的 intent 过滤器,系统可能会向该 activity 发送给定的 Intent

操作
对要执行的操作命名的字符串。通常是平台定义的值之一,比如 ACTION_SENDACTION_VIEW

使用 <action> 元素在您的 intent 过滤器中指定此内容。您在此元素中指定的值必须是操作的完整字符串名称,而非 API 常量(请参阅以下示例)。

数据
与 intent 关联的数据的说明。

使用 <data> 元素在您的 intent 过滤器中指定此内容。使用此元素中的一个或多个属性,您可以只指定 MIME 类型、URI 前缀、URI 架构,也可以指定这些内容的组合以及其他指示所接受数据类型的项。

注意:如果您无需声明关于数据 Uri 的具体信息(比如在您的 activity 处理的是其他类型的“额外”数据而不是 URI 的情况下),您应只指定 android:mimeType 属性,以声明您的 activity 处理的数据类型,比如 text/plainimage/jpeg

类别
提供另一种方式来描述处理 intent 的 activity 的特征,通常与用户手势或 activity 启动的位置有关。系统支持多种不同的类别,但大多数都很少使用。不过,所有隐式 intent 默认使用 CATEGORY_DEFAULT 进行定义。

使用 <category> 元素在您的 intent 过滤器中指定此内容。

在您的 intent 过滤器中,您可以通过声明嵌套在 <intent-filter> 元素中的具有相应 XML 元素的各项,来声明您的 activity 接受的条件。

例如,下面这个 activity 所包含的 intent 过滤器会在数据类型为文本或图像时处理 ACTION_SEND intent:

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
        <data android:mimeType="image/*"/>
    </intent-filter>
</activity>

提示:如果您希望选择器对话框中的图标与 activity 的默认图标不同,请在 <intent-filter> 元素中添加 android:icon

每个入站 intent 仅指定一项操作和一个数据类型,但可以在每个 <intent-filter> 中声明 <action><category><data> 元素的多个实例。

如果任何两对操作和数据的行为相斥,您应创建单独的 intent 过滤器,以指定与哪种数据类型配对时哪些操作可以接受。

例如,假定您的 activity 同时处理 ACTION_SENDACTION_SENDTO intent 的文本及图像。在这种情况下,您必须为两个操作定义两种不同的 intent 过滤器,因为 ACTION_SENDTO intent 必须使用数据 Uri 指定使用 sendsendto URI 架构的收件人地址。例如:

<activity android:name="ShareActivity">
    <!-- filter for sending text; accepts SENDTO action with sms URI schemes -->
    <intent-filter>
        <action android:name="android.intent.action.SENDTO"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
    </intent-filter>
    <!-- filter for sending text or images; accepts SEND action and text or image data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

注意:为了接收隐式 intent,您必须在 intent 过滤器中添加 CATEGORY_DEFAULT 类别。startActivity()startActivityForResult() 方法将所有 intent 当作声明了 CATEGORY_DEFAULT 类别一样对待。如果您没有在 intent 过滤器中声明该类别,任何隐式 intent 都不会解析为您的 activity。

如需详细了解如何发送和接收执行社交分享行为的 ACTION_SEND intent,请参阅关于从其他应用接收简单的数据的课程。您也可以在分享简单的数据分享文件中找到关于分享数据的有用信息。

处理您的 activity 中的 intent

为了决定在您的 activity 中执行哪项操作,您可以读取用于启动 activity 的 Intent

当您的 activity 启动时,调用 getIntent() 以检索启动 activity 的 Intent。您可以在 activity 生命周期的任何时间执行此操作,但通常应在早期回调(例如,onCreate()onStart())时执行。

例如:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.main)

    val data: Uri? = intent?.data

    // Figure out what to do based on the intent type
    if (intent?.type?.startsWith("image/") == true) {
        // Handle intents with image data ...
    } else if (intent?.type == "text/plain") {
        // Handle intents with text ...
    }
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    // Get the intent that started this activity
    Intent intent = getIntent();
    Uri data = intent.getData();

    // Figure out what to do based on the intent type
    if (intent.getType().indexOf("image/") != -1) {
        // Handle intents with image data ...
    } else if (intent.getType().equals("text/plain")) {
        // Handle intents with text ...
    }
}

返回结果

如果您想将结果返回给调用您 activity 的 activity,只需调用 setResult() 来指定结果代码和结果 Intent 即可。当您的操作完成且用户应返回原始 activity 时,调用 finish() 以关闭(并销毁)您的 activity。例如:

Kotlin

// Create intent to deliver some kind of result data
Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri")).also { result ->
    setResult(Activity.RESULT_OK, result)
}
finish()

Java

// Create intent to deliver some kind of result data
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri"));
setResult(Activity.RESULT_OK, result);
finish();

您必须始终为结果指定结果代码。通常,结果代码是 RESULT_OKRESULT_CANCELED。之后您可以根据需要使用 Intent 提供额外的数据。

注意:默认情况下,结果设置为 RESULT_CANCELED。因此,如果用户在完成操作和您设置结果前按了“返回”按钮,原始 activity 会收到“已取消”结果。

如果您只需返回指示若干结果选项之一的整数,则可以将结果代码设置为大于 0 的任何值。如果您使用结果代码传递整数,且无需包括 Intent,则可以调用 setResult() 并仅传递结果代码。例如:

Kotlin

setResult(RESULT_COLOR_RED)
finish()

Java

setResult(RESULT_COLOR_RED);
finish();

在这种情况下,只有几个可能的结果,因此结果代码是一个本地定义的整数(大于 0)。当您向自己应用中的 activity 返回结果时,这将非常有效,因为接收结果的 activity 可引用公共常量来确定结果代码的值。

注意:无需检查您的 activity 是通过 startActivity() 还是 startActivityForResult() 启动的。如果启动您 activity 的 intent 需要结果,只需调用 setResult() 即可。如果原始 activity 已经调用 startActivityForResult(),系统将向其传递您提供给 setResult() 的结果;否则,会忽略结果。