IntentFilter直譯過(guò)來(lái)就是意圖過(guò)濾器,我們可以通過(guò)它的匹配規(guī)則去打開我們想要打開的一類Activity,例如我們想要打開手機(jī)瀏覽器,但是我們不知道用戶安裝了哪些瀏覽器或者習(xí)慣于使用哪個(gè)瀏覽器,那么我們就可以通過(guò)IntentFilter來(lái)啟動(dòng),讓用戶自己選擇使用哪個(gè)瀏覽器。
IntentFilter可以在AndroidManifest.xml中注冊(cè)Activity時(shí)通過(guò)<intent-filter>標(biāo)簽來(lái)設(shè)置intentFilter,它有3個(gè)標(biāo)簽屬性action,category和data。
<activity
android:launchMode="standard"
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
在說(shuō)intentFilter的匹配規(guī)則前,有必要得先講一下Activity的調(diào)用模式,注意是調(diào)用模式而不是啟動(dòng)模式。Activity的調(diào)用模式有兩種:顯式調(diào)用和隱式調(diào)用。
-
顯式調(diào)用
大多數(shù)情況下我們最常接觸到的就是顯式調(diào)用了:
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
其實(shí)嚴(yán)格來(lái)講,這個(gè)也不算是顯式調(diào)用,因?yàn)樵陲@式調(diào)用的意義中需要明確之處被啟動(dòng)的對(duì)象的組件信息,包括包名和類名,這里并沒(méi)有之處包名:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName("com.mg.axe.testappa","com.mg.axe.testappa.MainActivity");
intent.setComponent(cn);
startActivity(intent);
-
隱式調(diào)用
需要Intent能匹配目標(biāo)組件的IntentFilter中所設(shè)置的過(guò)濾信息.如果不匹配將無(wú)法啟動(dòng)目標(biāo)Activity。
示例:
Intent intent = new Intent();
intent.setAction("android.intent.action.View");
startActivity(intent);
當(dāng)我們進(jìn)行Activity的隱式調(diào)用時(shí),IntentFilter就可以排上用場(chǎng)了,那么下面將詳細(xì)介紹其匹配規(guī)則:
-
Action的匹配規(guī)則
Intent中的action必須能夠和Activity過(guò)濾規(guī)則中的Action完全匹配(即完全相等)。一個(gè)過(guò)濾規(guī)則中有多個(gè)action,那么只要Intent中的action能夠和Activity過(guò)濾規(guī)則中的任何一個(gè)action相同即可匹配成功。簡(jiǎn)單的說(shuō)就是Intent中的action必須出現(xiàn)在目標(biāo)Activity的過(guò)濾規(guī)則中。
示例:
<!--SecondActivity的intent-filter-->
<intent-filter>
<category android:name = "android.intent.category.DEFAULT" />
<action android:name="com.axe.mg.what" />
</intent-filter>
<!--ThirdActivity的intent-filter-->
<intent-filter>
<category android:name = "android.intent.category.DEFAULT" />
<action android:name="com.axe.mg.what" />
<action android:name="com.axe.mg.how"/>
</intent-filter>
<!--FourthActivity的intent-filter-->
<intent-filter>
<category android:name = "android.intent.category.DEFAULT" />
<action android:name="com.axe.mg.why" />
<action android:name="com.axe.mg.how"/>
</intent-filter>
Intent intent = new Intent();
intent.setAction("com.axe.mg.what");
startActivity(intent);
這種啟動(dòng)方式既可以啟動(dòng)SecondActivity,也可以啟動(dòng)ThirdActivity,但是無(wú)法啟動(dòng)FourthActivity。且必須至少含有一個(gè)<category android:name = "android.intent.category.DEFAULT" />標(biāo)簽,否則系統(tǒng)會(huì)拋出ActivityNotFoundException的異常

-
category的匹配規(guī)則
一個(gè)Intent可以設(shè)置多個(gè)category,且Intent中的所有category都必須匹配到Activity中。也可以不設(shè)置category,這時(shí)系統(tǒng)會(huì)自動(dòng)匹配android.intent.category.DEFAULT。這里可能感覺(jué)和action很像,但是只要稍微注意一下就可以發(fā)現(xiàn)Intent是setAction和addCategory,也就是說(shuō)action只有一個(gè)(注意是一個(gè)Intent只有一個(gè)action,但是一個(gè)Activity的intent-filter中可以有多個(gè)action),而category可以有很多個(gè)且所有的category都必須出現(xiàn)在Activity的category集中。
示例:
<!--SecondActivity的intent-filter-->
<intent-filter>
<action android:name="com.axe.mg.what" />
<category android:name="com.yu.hu.category1"/>
<category android:name="com.yu.hu.category2"/>
<category android:name = "android.intent.category.DEFAULT" />
</intent-filter>
<!--ThirdActivity的intent-filter-->
<intent-filter>
<action android:name="com.axe.mg.what" />
<category android:name = "android.intent.category.DEFAULT" />
<category android:name="com.yu.hu.category1"/>
<category android:name="com.yu.hu.category2"/>
<category android:name="com.yu.hu.category3"/>
</intent-filter>
<!--FourthActivity的intent-filter-->
<intent-filter>
<action android:name="com.axe.mg.what" />
<category android:name = "android.intent.category.DEFAULT" />
<category android:name="com.yu.hu.category2"/>
</intent-filter>
Intent intent = new Intent();
intent.addCategory("com.yu.hu.category1");
intent.addCategory("com.yu.hu.category2");
intent.setAction("com.yu.hu.what");
startActivity(intent);
此時(shí)依然只能匹配到前兩個(gè)Activity,因?yàn)镕ourthActivity沒(méi)有category1。

另外這里還有兩點(diǎn)要注意:
- 因?yàn)閺?qiáng)制要求一個(gè)Activity需要一個(gè)
<category android:name="android.intent.category.DEFAULT"/>,所以我們不用將這個(gè)categoty添加到intent中去匹配。 - 如果單獨(dú)只
addCategory是沒(méi)有用的,必須setAction之后才行。
-
data的匹配規(guī)則
首先來(lái)說(shuō)一下data的結(jié)構(gòu),data由兩部分組成:mineType和URI。mineType指媒體類型,如.png.jpg等。而URI可配置更多信息:
- scheme:URI的模式,如
http。如果URI中沒(méi)有指定scheme,那么整個(gè)URI無(wú)效。默認(rèn)為content和file。- host:URI的
host(域名、網(wǎng)址),如www.baidu.com。如果指定了scheme和port,path等其他參數(shù),但是host未指定,那么整個(gè)URI無(wú)效;如果只指定了scheme,沒(méi)有指定host和其他參數(shù),URI是有效的。- port:URI端口,當(dāng)URI指定了
scheme和host參數(shù)時(shí)port參數(shù)才有意義。- path:用來(lái)匹配完整的路徑,如:http://example.com/blog/abc.html,這里將 path 設(shè)置為 /blog/abc.html 才能夠進(jìn)行匹配;
- pathPrefix:用來(lái)匹配路徑的開頭部分,拿上面的 URI 來(lái)說(shuō),這里將
pathPrefix設(shè)置為 /blog 就能進(jìn)行匹配了;- pathPattern:用表達(dá)式來(lái)匹配整個(gè)路徑。
總的來(lái)說(shuō)有點(diǎn)像是正則表達(dá)式,用于匹配指定字段內(nèi)容。
示例:假如我想要匹配https://www.baidu.com:8080/imgs/*,那么data應(yīng)該這么寫:
<intent-filter>
<action android:name="xx" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="www.baidu.com"
android:pathPrefix="/imgs"
android:port="8080"
android:scheme="https" />
</intent-filter>
java代碼:
Intent intent = new Intent();
intent.setData(Uri.parse("https://www.baidu.com:8080/imgs/img1.png"));
startActivity(intent);