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/jpegaudio/mpeg4-genericvideo/*

②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方法

前两种可以理解为一种,也就是说总共是两个具体的方法,分别是resolveActivityqueryIntentActivities
两者的区别是: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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值