Android 隐式启动Activity之:action,category,data

Android 启动Activity 分为两种:显示启动隐式启动

显示启动:就是通过Intent 指明 那个包名+类名Activity,是开发中最常用的启动方式,在这就不说了,不是本文的目标

隐示启动:现在说一下隐式启动。隐式启动也是通过Intent ,不过必须给 Intent 加上匹配数据,匹配数据必须和目标Activity的其中一个过滤器配上,方可启动目标Activity。关于 匹配数据和 过滤器,请看下面:

可以隐式启动的Activity,必须在清单文件 AndroidManifest.xml 里给这个Activity配置一个或多个过滤器<intent-filter>

下文 对 intent-filter 统称为:过滤器 

这个过滤器的作用是:外部可以启动我这个Activity,但必须要匹配上我其中一个 过滤器,就可以启动 这个Activity。

划重点!!!!------ 匹配上其中一个过滤器即可启动目标Activity

先上个Demo,过滤器是在 AndroidManifest.xml 里面给Activity配置的。比如:

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

            <intent-filter>
                <action android:name="FilterActivity_Action1"/>
                <action android:name="FilterActivity_Action2"/>
                <category android:name="FilterActivity_Category1"/>
                <category android:name="FilterActivity_Category2"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="test"
                      android:host="11"
                      android:port="8080">
                </data>
                <data android:scheme="test2"
                      android:host="22"
                      android:port="8081"
                      android:pathPattern="string"
                      android:path="/string"
                      android:mimeType="string">
                </data>
            </intent-filter>
        </activity>
 

很明显,FilterActivity 配置了两个过滤器 <intent-filter>,说了那么久,那到底怎么样才算成功匹配上一个过滤器呢?

先别急,我们先看一下过滤器里面的构造,看上面配置可以看到,一个过滤器有三种参数,分别是:

1>  action

2>  category

3>  data

1和2参数的类型是字符型。3是 Uri + mimeType

还有,这三种参数,每一种参数可以有一个或多个。比如上面的

action参数: 就有 FilterActivity_Action1 和 FilterActivity_Action2  两个参数

category参数:就有 FilterActivity_Category1 和 FilterActivity_Category2 两个参数

data参数: 有2个,形式是Uri + mimeType (具体是什么后面会说道)

现在暂且不说每个参数的细分匹配,就问:怎么才算完全匹配上一过滤器呢?

答:就是一个Intent 必须匹同时 配上这个过滤器的 三个条件:action,category和 data 

怎么才能算匹配上呢,我们一个一个拆分

==========【action匹配规则】=============

action是一种字符串,其实系统自己也定义了一些字符串,比如:android.intent.action.MAIN

但是我们可以自己定义比如上面的:FilterActivity_Action1 和 FilterActivity_Action2 

action的匹配规则是:只要Intent 的action和 过滤器其中一个 action匹配上,就算匹配成功。这里匹配是指字符串的完全一模一样。区分大小写的。比如上面代码,只要Intent的Action 设置成:FilterActivity_Action1 或 FilterActivity_Action2 ,都可以匹配成功。

还有一点的是:Intent的Action 必须要有的,不设置不能匹配成功。因为不设置就不能和过滤器任何一个Action匹配上了。

==========【category匹配规则】=============

category  其实和 action  类似,也是一种字符串,其实系统自己同样也定义了一些字符串,同样可以自己定义。匹配也是字符串的完全一模一样的匹配。

如上面的 category  FilterActivity_Category1 和 FilterActivity_Category2

category  其实和 action  不同的是,category   可以不写。不写也可以匹配成功。

但是Intent 只要配置了 category,那 Intent 的 所有 category ,必须 和 过滤器中匹配成功。否则匹配失败。

换句话说,Intent 设置的category ,必须是 过滤器中有的,只要过滤器中没有,都是失败的。

比如就拿上面代码来说:

我的Intent 设置  FilterActivity_Category1 , FilterActivity_Category2 和 FilterActivity_Category3

但过滤器只有 FilterActivity_Category1 和 FilterActivity_Category2

那就匹配失败。

还有一点说明下,系统在调用 startActivity时,会默认给我们的 Intent 加上  android.intent.category.DEFAULT

这个 category的。所以没如果你的 Activity 是想要 可以隐式启动的,那就必须在每一个过滤器里面 配置上:

<category android:name="android.intent.category.DEFAULT"/>  不然就无法启动。

为什么呢? 其实上面已经说得很清楚了。。。。。

==========【data匹配规则】=============

data  Intent中必须含有data,并且Intent中的每一个data,必须和过滤器中的匹配上。

但,data的匹配规则是什么呢?这个和前面两个不一样,不是单纯的字符串匹配。

在说data 的匹配规则之前,先补充一下data的形式:

data由两部分组成:Uri 和 mimeType  即:

data = Uri  +  mimeType

【mimeType】是指媒体类型,image/pngaudio/mpeg4-generic video/* 等,分别指图片,文本,视频等

【Uri 】 :的形式是:<scheme> : //<host> : <port>/  <path> |  <pathPrefix> | <pathPattern>

比如:https://www.baidu.com:8080/sraech/football content://com.demo.test:200//folder/subfolder/etd   

scheme 是 Uri 的形式,可以是:file,coontent,http等

Host 是域名,比如:www.baidu.com

port 是端口,比如:8080

path,pathPrefix 和 pathPattern 表示路径的参数

那说了一大通解析,怎么才能算匹配上呢?

规则1---不指定了Uri

如:

<data android:mimeType="image/*">
</data>

如果没有指定Uri ,那系统会默认给这个data 设置Uri,是:content 或 File

现在的 mimeType 是 Image类型.Intent 的data,比如是 file或conten,类型是 Image

比如:

Intent intent = new Intent();
intent.setDataAndType(Uri.parse("file://abcd"),"image/png");

这样Intent放 data方可 匹配过滤器中的data。

这里提醒一下,设置data 和 type时,要调用 setDataAndType()这个方法。

不要先调用 setData() 再调用 setType() ,这两方法会同时清掉对方。看源码就知道了。

规则2---指定了Uri

比如:

<data android:scheme="http" android:host="www.test.com" android:mimeType="video/mpeg"></data>
<data android:scheme="http" android:host="www.test.com" android:mimeType="audio/mpeg"></data>

那么,Intent 必须这么配置,才能匹配上 data

intent.setDataAndType(Uri.parse("http://www.test.com"),"video/mpeg");

或者

intent.setDataAndType(Uri.parse("http://www.test.com"),"audio/mpeg");

举了两个例子,基本上就清晰。

data的匹配规则就是:必须同时匹配上 Uri 和 mimeType

好了,我们给几个完整的 过滤器,比如:

            <intent-filter>
                <action android:name="action1"/>
                <action android:name="action2"/>
                <category android:name="category1"/>
                <category android:name="category2"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="test1" android:host="11" android:port="8080"></data>
                <data android:scheme="http" android:host="www.test.com" android:mimeType="video/mpeg"></data>
                <data android:scheme="http" android:host="www.test.com" android:mimeType="audio/mpeg"></data>
            </intent-filter>

然后我们通过隐式启动这个Activty:

/**
     *      隐式启动Activity
     * */
    public void test(Activity activity) {
        Intent intent = new Intent();
        //Action只需匹配上一个即可
        intent.setAction("action1");
        //Category必须全部匹配上
        intent.addCategory("category1");
        intent.addCategory("category2");
        //android.intent.category.DEFAULT 这个加不加都没问题,
        // 因为系统会默认给Intent加上,但是AndroidManifest.xml里就必须加上
        intent.addCategory("android.intent.category.DEFAULT");
        //Action只需匹配上一个即可
        intent.setDataAndType(Uri.parse("http://www.test.com"), "video/mpeg");
        activity.startActivity(intent);
    }

上面代码亲测可以启动目标Activity.

最后,总结一下。

action

Intent 必须设置 action ,过滤器中必须有与之一模一样的 action,否则匹配失败。Intent最多只能设置一个action ,因为每一次setAction 就会把前面的action 覆盖。看源码得知......

 

category

Intent 必须设置 category,可以设置多个,只要Intent设置了 的category,过滤器中就必须有。否则匹配失败。

提醒:系统会默认给Intent 添加上 android.intent.category.DEFAULT,所以能被隐式启动的Activity,必须给过滤器添加上这个category.

 

data

Intent 必须设置 data,过滤器中必须有与匹配的的 data,所谓与之匹配就是 :Uri 和 mimeType都必须一模一样。否则匹配失败。Intent最多只能设置一个data,因为每一次setDataAndType就会把前面的覆盖。看源码得知......

intent-filter 过滤器

一个Activity 可以有多个过滤器。每个过滤器必须同时有一个或多个action,category 和 data。

Intent 只要匹配上其中一个过滤器,就可以启动这个Activity.

而匹配上这个过滤器,就是同时匹配上这个过滤器的 action,category和data.

上面说的 intent-filter 其实同样适用于 BroadcastReceiver 和 Service。

只不过,系统建议 Service 尽量用 显示启动。

以上·代码亲测没问题,有问题请留言。谢谢!

猜你喜欢

转载自blog.csdn.net/Leo_Liang_jie/article/details/92836838