Android 启动Activity 分为两种:显示启动 和 隐式启动
显示启动:就是通过Intent 指明 那个包名+类名Activity,是开发中最常用的启动方式,在这就不说了,不是本文的目标
隐示启动:现在说一下隐式启动。隐式启动也是通过Intent ,不过必须给 Intent 加上匹配数据,匹配数据必须和目标Activity的其中一个过滤器配上,方可启动目标Activity。关于 匹配数据和 过滤器,请看下面:
可以隐式启动的Activity,必须在清单文件 里给这个Activity配置一个或多个过滤器<intent-filter>,
下文 对 intent-filter 统称为:过滤器
这个过滤器的作用是:外部可以启动我这个Activity,但必须要匹配上我其中一个 过滤器,就可以启动 这个Activity。
划重点!!!!------ 匹配上其中一个过滤器即可启动目标Activity
先上个Demo,过滤器是在 里面给Activity配置的。比如:
<activity android:name=".">
<intent-filter>
<action android:name=""/>
<category android:name=""/>
</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=""/>
<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是一种字符串,其实系统自己也定义了一些字符串,比如:
但是我们可以自己定义比如上面的: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 加上
这个 category的。所以如果你的 Activity 是想要 可以隐式启动的,那就必须在每一个过滤器里面 配置上:
<category android:name=""/> 不然就无法启动。
为什么呢? 其实上面已经说得很清楚了。。。。。
==========【data匹配规则】=============
data Intent中必须含有data,并且Intent中的每一个data,必须和过滤器中的匹配上。
但,data的匹配规则是什么呢?这个和前面两个不一样,不是单纯的字符串匹配。
在说data 的匹配规则之前,先补充一下data的形式:
data由两部分组成:Uri 和 mimeType 即:
data = Uri + mimeType
【mimeType】是指媒体类型,image/png,audio/mpeg4-generic 和 video/* 等,分别指图片,文本,视频等
【Uri 】 :的形式是:<scheme> : //<host> : <port>/ <path> | <pathPrefix> | <pathPattern>
比如::8080/sraech/football 或 content://:200//folder/subfolder/etd
scheme 是 Uri 的形式,可以是:file,coontent,http等
Host 是域名,比如:
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();
(("file://abcd"),"image/png");
这样Intent 设置的data方可匹配过滤器中的data。
这里提醒一下,设置data 和 type时,要调用 setDataAndType()这个方法。
不要先调用 setData() 再调用 setType() ,这两方法会同时清掉对方。看源码就知道了。
【规则2---指定了Uri】
比如:
<data android:scheme="http" android:host="" android:mimeType="video/mpeg"></data>
<data android:scheme="http" android:host="" android:mimeType="audio/mpeg"></data>
那么,Intent 必须这么配置,才能匹配上 data
((""),"video/mpeg");
或者
((""),"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=""/>
<data android:scheme="test1" android:host="11" android:port="8080"></data>
<data android:scheme="http" android:host="" android:mimeType="video/mpeg"></data>
<data android:scheme="http" android:host="" android:mimeType="audio/mpeg"></data>
</intent-filter>
然后我们通过隐式启动这个Activty:
/**
* 隐式启动Activity
* */
public void test(Activity activity) {
Intent intent = new Intent();
//Action只需匹配上一个即可
("action1");
//Category必须全部匹配上
("category1");
("category2");
// 这个加不加都没问题,
// 因为系统会默认给Intent加上,但是里就必须加上
("");
//Action只需匹配上一个即可
((""), "video/mpeg");
(intent);
}
上面代码亲测可以启动目标Activity.
最后,总结一下。
【action】
Intent 必须设置 action ,过滤器中必须有与之一模一样的 action,否则匹配失败。Intent最多只能设置一个action ,因为每一次setAction 就会把前面的action 覆盖。看源码得知......
【category】
Intent 必须设置 category,可以设置多个,只要Intent设置了 的category,过滤器中就必须有。否则匹配失败。
提醒:系统会默认给Intent 添加上 ,所以能被隐式启动的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 尽量用 显示启动。
以上·代码亲测没问题,有问题请留言。谢谢!