允许其他应用启动你的 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 对象的以下条件,则系统可能会将给定的 Intent 发送给该 Activity:

操作
指定要执行操作的字符串。通常是平台定义的值之一,例如 ACTION_SENDACTION_VIEW

使用 <action> 元素在 intent 过滤器中指定此项。你在此元素中指定的值必须是操作的完整字符串名称,而不是 API 常量,如本页的示例所示。

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

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

注意:如果你不需要声明有关数据 Uri 的具体信息,例如当你的 Activity 处理其他类型的“额外”数据而不是 URI 时,则只需指定 android:mimeType 属性来声明你的 Activity 处理的数据类型,例如 text/plainimage/jpeg

类别
提供了一种额外的方式来描述处理 intent 的 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 中执行何种操作,请读取用于启动它的 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() 的结果发送给它;否则,结果将被忽略。