0
点赞
收藏
分享

微信扫一扫

IntentFilter的匹配规则随想录


前言

本人对Activity的两种启动,尤其是隐式启动有了新的理解,特此记录

1.Activity两种启动方式

①显式启动:需要明确地指定被启动对象的组件信息,包括包名和类名
(一般用在一个应用程序内部)

例如

Intent intent = new Intent();
intent.setClass(SecondActivity.this,ThirdActivity.class);
startActivity(intent);

②隐式启动:需要Intent能够匹配目标组件的intent-filter中所设置的过滤信息。主要是有三个:action、category、data,并且这三个同时匹配,才能够启动
(一般用在不同应用程序之间)

例如

Intent intent = new Intent("com.ryg.charpter_1.c");
intent.addCategory("com.ryg.category.c");
intent.setDataAndType(Uri.parse("content://abc"),"text/plain");
startActivity(intent);

对应的Activity可以是

<activity
android:name="com.ryg.chapter_1.ThirdActivity"
android:configChanges="screenLayout"
android:label="@string/app_name"
android:taskAffinity="com.ryg.task1" >
<intent-filter>
<action android:name="com.ryg.charpter_1.c" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

值得一提的是,一个Activity中可以有多个intent-filter,一个Intent只要能匹配其中任何一组intent-filter即可启动对应的Activity

2.action、category、data的匹配规则

(1)action的匹配规则

①要求字符串完全相同
②要求Intent中必须有action,且必须和intent-filter中的其中一个action相匹配(规则就是字符串完全相同)

(2)category的匹配规则

①category可以不设置
②如果设置,则和action的匹配规则一样

  • 问题:category不设置,怎么玩?

其实如果要让我们的activity能够接收隐式调用,就必须在intent-filter中指定​​"android.intent.category.DEFAULT"​​​这个category。然后如果没有在Intent中设置category,则当我们调用​​startActivity​​​或者​​startActivityForResult​​​的时候会默认为Intent加上​​"android.intent.category.DEFAULT"​​,所以可以匹配成功,没毛病。

(3)data的匹配规则

和action基本一样,区别是,如果intent-filter中没有指定data,那么Intent里面可以不设置。而action是必须要在intent-filter中最少指定一个

  • data由两部分组成,mimeType(媒体类型)和URI

①mimeType(媒体类型)
一般包括​​​image/jpeg​​​,​​audio/mpeg4-generic​​​和​​video/*​​等

②URI
URI的结构为

​<scheme>//<host>:<port>/[<path> | <pathPrefix>|<pathPattern>]​

scheme:URI的模式,比如http、file、content等,如果URI中没有指定scheme,那么整个URI的其他参数无效。
host:URI的主机名,比如www.baidu.com,如果host没有指定那么整个URI的其他参数无效。
port:URI的端口号。
path,pathPattern,pathPrefix:这三个参数指定路径信息

URI的例子:
​​​content://com.example.project:200/folder/subfolder/etc​​​​http://www.baidu.com:80/search/info​

3.使用的正确姿势

一般使用隐式方式启动一个Activity的时候,要做一个判断,来看是否有匹配Intent的Activity。那么这个判断的方法有三种,分别是

PackageManager的​​resolveActivity​​​方法
Intent的​​​resolveActivity​​​方法
PackageManager的​​​queryIntentActivities​​方法

前两种可以理解为一种,也就是说总共是两个具体的方法,分别是​​resolveActivity​​​和​​queryIntentActivities​​​。
两者的区别是:​​​resolveActivity​​​返回最佳匹配的Activity信息,​​queryIntentActivities​​返回所有成功匹配的Activity信息。

使用实例如下

if (getPackageManager().resolveActivity(intent, 0) == null) {  

// 说明系统中不存在这个activity
}

if(intent.resolveActivity(getPackageManager()) == null) {

// 说明系统中不存在这个activity
}

List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, 0);
if (list.size() == 0) {
// 说明系统中不存在这个activity
}

其中,最后面这个0是个​​flags​​​,内部其实是​​MATCH_DEFAULT_ONLY​​​这个标记位,它的含义是仅仅匹配那些在intent-filter中声明了​​"android.intent.category.DEFAULT"​​的这个category的Activity。从而使得匹配出来的Activity全都是支持隐式调用的,避免出现虽然匹配但是不支持隐式调用的这种问题。

4.经典的组合

​<action android:name="android.intent.action.MAIN"/>​​​​<category android:name="android.intent.category.LAUNCHER">​

这一对表明这是一个程序的入口Activity。


举报

相关推荐

0 条评论