The Android Developer Challenge is back! Submit your idea before December 2.

允许其他应用启动您的 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 与在数据类型为文本或图像时处理 ACTION_SEND Intent 的 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() 将按照其声明 CATEGORY_DEFAULT 类别的方式处理所有 Intent。如果您不在 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() 的结果;否则,会忽略结果。