Android之Intent Filter匹配规则(隐式Intent跳转)

注意:本篇文章是本人阅读相关文章所写下的总结,方便以后查阅,所有内容非原创,侵权删。

本篇文章内容来自于:
你必须弄懂的Intent Filter匹配规则
史上最全intent-filter匹配规则,没有之一

目录

  1. 什么是Intent Filter(intentFilter+data+category)
  2. action的匹配规则/setAction
  3. data的匹配规则(uri+mimetype)/setData、setType、setDataAndType
  4. category的匹配规则 addCategory
  5. Extra
    --5.1 intent-filter匹配优先级
    --5.2 查询是否有Activity可以匹配我们指定Intent的组件

1. 什么是Intent Filter

Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。

在这个解析过程中,Android是通过Intent的action、type、category这三个属性来进行匹配判断的,只有完全匹配才能启动Activity。
若声明了多个Intent Filter,只需要匹配任意一个即可启动该组件。

        <activity
            android:name="com.saiermeng.intent.SecondActivity"
            android:label="@string/title_activity_second">
            <intent-filter>
                <action android:name="com.saiermeng.intent.open02" />
                <data
                    android:host="www.saiermeng.com"
                    android:path="/java"
                    android:port="8080"
                    android:scheme="http"></data>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

2. action的匹配规则

action是一个字符串。

如果Intent指明定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,否则不能匹配。
可通过setAction方法为Intent设置action,也可在构造Intent时传入action。
需要注意的是,隐式Intent必须指定action

一个Intent Filter中可声明多个action,Intent中的action与其中的任一个action在字符串形式上完全相同(注意,区分大小写,大小写不同但字符串内容相同也会造成匹配失败),action方面就匹配成功

比如:

<intent-filter>
    <action android:name="android.intent.action.SEND"/>
    <action android:name="android.intent.action.SEND_TO"/>
</intent-filter>

//那么只要Intent的action为“SEND”或“SEND_TO”,那么这个Intent在action方面就能和上面那个Activity匹配成功。
Intent intent = new Intent("android.intent.action.SEND") ;

Android系统预定义了许多action,这些action代表了一些常见的操作。常见action如下(Intent类中的常量):

Intent.ACTION_VIEW
Intent.ACTION_DIAL
Intent.ACTION_SENDTO
Intent.ACTION_SEND
Intent.ACTION_WEB_SEARCH

3. data的匹配规则

如果Intent没有提供type,系统将从data中得到数据类型。

只要Intent的data只要与Intent Filter中的任一个data声明完全相同,data方面就完全匹配成功。

data由两部分组成:mimeType和URI

MineType指的是媒体类型:例如image/jpeg,auto/mpeg4和viedo/*等,可以表示图片、文本、视频等不同的媒体格式
常用的文件的mine type类型

URI格式如下

<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern >]
//比如
 content://com.wooyun.org:200/folder/etc 
 http://www.wooyun.org/search/info

Intent的uri可通过setData方法设置,mimetype可通过setType方法设置。

若Intent Filter的data声明部分未指定uri,则缺省uri为content或file,Intent中的uri的scheme部分需为content或file才能匹配;

若要为Intent指定完整的data,必须用setDataAndType方法
因为setData和setType方法的源码中会彼此互相清除对方的值,即setData会把mimeType置为null,setType会把uri置为null。

<data 
//scheme:整个URI的模式,如常见的http,file等
//注意如果URI中没有指定的scheme,那么整个uri无效
          android:scheme="String"
//host:URI的域名,比如我们常见的www.mi.com、www.baidu.com
//与scheme一样,一旦没有host那么整个URI也毫无意义;
          android:host="String" 
//port:端口号,比如80
//只有在URI中指定了scheme和host之后端口号才是有意义的;
          android:port="String"
//path:表示完整的路径
          android:path="String" 
//pathPattern在path基础上可以包含通配符
          android:pathPattern="String"
//pathPrefix:表示路径的前缀信息
          android:pathPrefix="String"
//MineType指的是媒体类型:例如image/jpeg,auto/mpeg4和viedo/*等,可以表示图片、文本、视频等不同的媒体格式
          android:mimeType="String"/>

path、pathPrefix、pathPattern 之间的区别
比如http://example.com/blog/abc.html
path用来匹配完整的路径,这里将 path 设置为 /blog/abc.html 才能够进行匹配;
pathPrefix 用来匹配路径的开头部分,这里将 pathPrefix 设置为 /blog 就能进行匹配了;
pathPattern 用表达式来匹配整个路径

关于表达式中的匹配符号与转义
匹配符号
” 用来匹配0次或更多,如:“a” 可以匹配“a”、“aa”、“aaa”…
“.” 用来匹配任意字符,如:“.” 可以匹配“a”、“b”,“c”…
因此 “.” 就是用来匹配任意字符0次或更多,如:“.html” 可以匹配 “abchtml”、“chtml”,“html”,“sdf.html”…
转义:因为当读取 Xml 的时候,“/” 是被当作转义字符的(当它被用作 pathPattern 转义之前),因此这里需要两次转义,读取 Xml 是一次,在 pathPattern 中使用又是一次。如:“” 这个字符就应该写成 “//”,“/” 这个字符就应该写成 “////”。

使用案例

//案例一:打开pdf文件显示自己的应用
//匹配 http 以 “.pdf” 结尾的路径
//使得别的程序想要打开网络 pdf 时,用户能够可以选择我们的程序进行下载查看。
<intent-filter>  
    <action android:name="android.intent.action.VIEW"></action>  
    <category android:name="android.intent.category.DEFAULT"></category>  
    <data android:scheme="http" android:pathPattern=".*//.pdf"></data>  
</intent-filter>  

//案例二:使用户转发信息时显示自己的应用
//如果我们做的是一个IM应用,或是其他类似于微博之类的应用
//让别人转发信息时通过 Intent 进行调用时出现在选择框里
//我们只用注册 android.intent.action.SEND 与 mimeType 为 “text/plain” 或 “/” 就可以了
<intent-filter>  
    <action android:name="android.intent.action.SEND" />  
    <category android:name="android.intent.category.DEFAULT" />  
    <data mimeType="*/*" />  
</intent-filter> 

//案例三:当用户打开音乐文件出现我们的应用
//如果我们做的是一个音乐播放软件,当文件浏览器打开某音乐文件的时候,使我们的应用能够出现在选择框里。
//我们只用注册 android.intent.action.VIEW 与 mimeType 为 “audio/*” 就可以了
<intent-filter>  
     <action android:name="android.intent.action.VIEW" />  
     <category android:name="android.intent.category.DEFAULT" />  
     <data android:mimeType="audio/*" />  
</intent-filter> 
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

区别一: 
android.intent.action.MAIN决定一个应用程序最先启动那个组件 
android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里(说白了就是是否在桌面上显示一个图标) 
这两个属性组合情况: 
第一种情况:有MAIN,无LAUNCHER,程序列表中无图标 
原因:android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里 
第二种情况:无MAIN,有LAUNCHER,程序列表中无图标 
原因:android.intent.action.MAIN决定应用程序最先启动的Activity,如果没有Main,则不知启动哪个Activity,故也不会有图标出现 
所以这两个属性一般成对出现。 
如果一个应用中有两个组件intent-filter都添加了android.intent.action.MAIN和 
android.intent.category.LAUNCHER这两个属性, 则这个应用将会显示两个图标, 写在前面的组件先运行。 

区别二:
android.intent.category.LAUNCHER:android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里,就是android开机后的主程序列表。 
android.intent.category.HOME:按住“HOME”键,该程序显示在HOME列表里。

4. category的匹配规则

category也是一个字符串。

它要求Intent中如果出现了category,不管有几个category,对于每个category来说,它必须是过滤规则中的定义了的category。

当然,Intent中也可以没有category(若Intent中未指定category,系统会自动为它带上“android.intent.category.DEFAULT”),如果没有,仍然可以匹配成功。

category和action的区别在于,
action要求Intent中必须有一个action且必须和过滤规则中的某几个action相同,
而category要求Intent可以没有category,但是一旦发现存在category,不论你有多少,每个都要能够和过滤规则中的任何一个category相同。

我们可以通过addCategory方法为Intent添加category。

每一个通过 startActivity() 方法发出的隐式 Intent 都至少有一个 category,就是 “android.intent.category.DEFAULT”,所以只要是想接收一个隐式 Intent 的 Activity 都应该包括 “android.intent.category.DEFAULT” category,不然将导致 Intent 匹配失败.

5. Extra

5.1 intent-filter匹配优先级

首先查看Intent的过滤器(intent-filter),按照以下优先关系查找:action->data->category

参考链接:http://blog.csdn.net/cnnumen/article/details/8464786

5.2 查询是否有Activity可以匹配我们指定Intent的组件

采用PackageManager的resolveActivity或者Intent的resolveActivity方法会获得最适合Intent的一个Activity
调用PackageManager的queryIntentActivities会返回所有成功匹配Intent的Activity

应用:杜绝异常的发生
如果intent匹配不到,会抛出异常。
为了避免发生以上异常,我们可以使用PackageManager或者Intent的resolveActivity()方法,如果intent和过滤规则匹配失败,那么将返回null,我们也就不会再继续调用startActivity方法啦,从而去修改intent再次进行匹配直到成功匹配到预期intent。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容