赞
踩
Android 启动Activity 分为两种:显示启动 和 隐式启动
显示启动:就是通过Intent 指明 那个包名+类名Activity,是开发中最常用的启动方式,在这就不说了,不是本文的目标
隐示启动:现在说一下隐式启动。隐式启动也是通过Intent ,不过必须给 Intent 加上匹配数据,匹配数据必须和目标Activity的其中一个过滤器配上,方可启动目标Activity。关于 匹配数据和 过滤器,请看下面:
可以隐式启动的Activity,必须在清单文件 AndroidManifest.xml 里给这个Activity配置一个或多个过滤器<intent-filter>,
下文 对 intent-filter 统称为:过滤器
这个过滤器的作用是:外部可以启动我这个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>
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
很明显,FilterActivity 配置了两个过滤器 <intent-filter>,说了那么久,那到底怎么样才算成功匹配上一个过滤器呢?
先别急,我们先看一下过滤器里面的构造,看上面配置可以看到,一个过滤器有三种参数,分别是:
1和2参数的类型是字符型。3是 Uri + mimeType
还有,这三种参数,每一种参数可以有一个或多个。比如上面的
action参数: 就有 FilterActivity_Action1 和 FilterActivity_Action2 两个参数
category参数:就有 FilterActivity_Category1 和 FilterActivity_Category2 两个参数
data参数: 有2个,形式是Uri + mimeType (具体是什么后面会说道)
现在暂且不说每个参数的细分匹配,就问:怎么才算完全匹配上一过滤器呢?
答:就是一个Intent 必须匹同时 配上这个过滤器的 三个条件:action,category和 data
怎么才能算匹配上呢,我们一个一个拆分
action是一种字符串,其实系统自己也定义了一些字符串,比如:android.intent.action.MAIN
但是我们可以自己定义比如上面的:FilterActivity_Action1 和 FilterActivity_Action2
action的匹配规则是:只要Intent 的action和 过滤器其中一个 action匹配上,就算匹配成功。这里匹配是指字符串的完全一模一样。区分大小写的。比如上面代码,只要Intent的Action 设置成:FilterActivity_Action1 或 FilterActivity_Action2 ,都可以匹配成功。
还有一点的是:Intent的Action 必须要有的,不设置不能匹配成功。因为不设置就不能和过滤器任何一个Action匹配上了。
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 Intent中必须含有data,并且Intent中的每一个data,必须和过滤器中的匹配上。
但,data的匹配规则是什么呢?这个和前面两个不一样,不是单纯的字符串匹配。
在说data 的匹配规则之前,先补充一下data的形式:
data由两部分组成:Uri 和 mimeType 即:
【mimeType】是指媒体类型,image/png,audio/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);
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
上面代码亲测可以启动目标Activity.
最后,总结一下。
Intent 必须设置 action ,过滤器中必须有与之一模一样的 action,否则匹配失败。Intent最多只能设置一个action ,因为每一次setAction 就会把前面的action 覆盖。看源码得知......
Intent 必须设置 category,可以设置多个,只要Intent设置了 的category,过滤器中就必须有。否则匹配失败。
提醒:系统会默认给Intent 添加上 android.intent.category.DEFAULT,所以能被隐式启动的Activity,在 AndroidManifest.xml 必须给过滤器添加上这个category.
Intent 必须设置 data,过滤器中必须有与匹配的的 data,所谓与之匹配就是 :Uri 和 mimeType都必须一模一样。否则匹配失败。Intent最多只能设置一个data,因为每一次setDataAndType就会把前面的覆盖。看源码得知......
一个Activity 可以有多个过滤器。每个过滤器必须同时有一个或多个action,category 和 data。
Intent 只要匹配上其中一个过滤器,就可以启动这个Activity.
而匹配上这个过滤器,就是同时匹配上这个过滤器的 action,category和data.
上面说的 intent-filter 其实同样适用于 BroadcastReceiver 和 Service。
只不过,系统建议 Service 尽量用 显示启动。
以上·代码亲测没问题,有问题请留言。谢谢!
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。