Intent过滤器

隐式启动Activity时,并没有在Intent中指明Acitivity所在的类,因此,Android系统一定存在某种匹配机制,使Android系统能够根据Intent中的数据信息,找到需要启动的Activity。这种匹配机制是依靠Android系统中的Intent过滤器(Intent Filter)来实现的。
Intent过滤器是一种根据Intent中的动作(action)、类别(category)和数据(data)等内容。对适合接收该 Intent 的组件进行匹配和筛选的机制。Intent过滤器可以匹配数据类型、路径和协议,还可以确定多个品牌项顺序的优先级(priority)。应用程序的Activity、Service和 BroadcastReceiver 组件都可以注册Intent过滤器。这样,这些组件在特定的数据格式上则可以产生相应的动作。
为了使组件能够注册Intent过滤器,通常在AndroidManifest.xml 文件的各个组件下定义 < intent-filter >节点,然后再< intent-filter >节点中声明该组件所支持的动作、执行的环境和数据格式等信息。当然,也可以在程序代码中动态的为组件设置Intent过滤器。< intent-filter >节点支持< action >标签 、 < category >标签 和 < data >标签,分别用来定义Intent过滤器的动作、类型和数据。 < intent-filter >节点支持的标签和属性说明如下图:
< intent-filter > 节点属性

标签 属性 说明
action android: name 指定组件所能响应的动作
category android: category 指定以何种方式去服务Intent请求的动作
data Android: host
android: mimetype
android: path
android: port
android: scheme
指定一个有效的主机名
指定组件能处理的数据类型
有效的URI路径名
主键的有效端口号
所需要的特定协议

< category >标签用来指定Intent过滤器的服务方式,每个Intent过滤器可以定义多个< category >标签,我们可以使用自定义的类别,或者使用系统提供的类别。Android系统提供的类别可以参考下表:

说明
ALTERNATIVE Intent数据默认动作的一个可替换的执行方法
SELECTED_ALTERNATIVE 和ALTERNATIVE类似,但替换的执行方法不是指定的,而是被解析出来的
BROWSABLE 生命Activity可以有浏览器启动
DEFAULT 为Intent过滤器中定义的数据提供默认动作
HOME 设备启动后显示的第一个Activity
LAUNCHER 在应用程序启动时首先被显示

这种Intent 到 Intent 过滤器的映射过程称为“Intent解析”。Intent解析可以在所有的组件中,找到一个可以与请求的Intent达成最佳匹配的Intent过滤器。Android系统中Intent解析的匹配规则为:

  1. Android系统把所有应用程序包中的 Intent 过滤器集合在一起,形成一个完整的Intent过滤器列表。
  2. 在Intent与Intent过滤器进行匹配时,Android系统会将列表中所有Intent过滤器的“动作”和“类别”与Intent进行匹配,任何不匹配的Intent过滤器都将被过滤掉。没有指定“动作”的Intent过滤器可以匹配任何的Intent,但是没有指定“类别”的Intent过滤器只能匹配没有“类别”的Intent。
  3. 把Intent数据Uri的每个子部与Intent过滤器的< data >标签中的属性进行匹配,如果< data >标签指定了协议、主机名、路径名或MIME类型,那么这些属性都要与Intent的Uri数据部分进行匹配,任何不匹配的Intent过滤器均被过滤掉。
  4. 如果Intent过滤器的匹配结果多于一个,则可以根据在< intent-filter >标签中定义的优先级标签来对Intent过滤器进行排序,优先级最高的Intent过滤器将被选择。

    IntentResolutionDemo示例说明了如何在AndroidManifest.xml文件中注册Intent过滤器,以及如何设置< intent - filter >节点属性来捕获指定的Intent。
    AndroidManifest.xml的完整代码示例如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.satellitemenu">
    <application  android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".MyActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.LAUNCHER" />
            <data android:scheme="schemodemo" android:host="edu.hrbeu"/>
            </intent-filter>
        </activity>

    </application>
</manifest>

第一个Activity 的 Intent 过滤器:

动作是android.intent.action.MAIN,类别是android.intent.category.LAUNCHER ,由此可知,这个Activity是应用程序启动后显示的默认用户界面。

第二个Activity的Intent过滤器

动作是android.intent.action.VIEW,表示根据Uri协议,以浏览的方式启动相应的Activity;类别是android.intent.category.DEFAULT ,表示数据的默认动作;数据的协议部分是:android:scheme="schemodemo",数据的主机名称部分是 android:host="edu.hrbeu"。

在MainActivity.java文件中,定义了一个Intent用来启动另一个Activity,这个Intent与Activity设置的过滤器是完全匹配的。相关代码如下:

Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("schemodemo://edu.hrbeu/path"));
startActicity(intent);

代码中首先定义Intent,动作为Intent.ACTION_VIEW,与Intent过滤器的动作android.intent.action.VIEW匹配;Uri是shemodemo://edu.hrbeu/path,其中的协议部分为schemodemo,主机名为edu.hrbeu,也与Intent过滤器定义的数据要求完全匹配。因此代码中定义的Intent,在Android系统与Intent过滤器列表进行匹配时,会与AndroidManifest.xml文件中MyActivity定义的Intent过滤器完全匹配。

你可能感兴趣的:(android,filter)