Intent有兩種,一種是顯式意圖,一種是隱式意圖。顯式意圖指定了具體要啟動(dòng)的Activity的類,所以當(dāng)你打算用顯式意圖啟動(dòng)某個(gè)Activity的時(shí)候,設(shè)置intent-filter是完全沒(méi)有用的。
對(duì)于每一個(gè)activity,可以有任意數(shù)量的intent-filter,在隱式意圖的匹配過(guò)程當(dāng)中,只要匹配上了任意一個(gè)intent-filter都能啟動(dòng)這個(gè)Activity。
intent-filter過(guò)濾intent根據(jù)三樣?xùn)|西,action,category和data。
action
action是區(qū)分大小寫(xiě)的字符串,一個(gè)intent-filter可以包含一個(gè)或多個(gè)action。當(dāng)然,一個(gè)action都沒(méi)有也是可以的,但是沒(méi)有action的intent-filter是無(wú)法被成功匹配的。無(wú)論intent-filter里面有一個(gè)還是多個(gè)actions,intent的action只要和intent-filter里面這些actions有一個(gè)完全相同就行。
category
category是區(qū)分大小寫(xiě)的字符串,一個(gè)intent-filter可以包含任意數(shù)量的category。但是如果希望intent-filter被成功匹配,category必須至少包含"android.intent.category.DEFAULT"。category的匹配規(guī)則是intent的category一定是intent-filter里面列舉的幾個(gè)category之一,或者說(shuō)intent的category不能超出intent-filter所列舉的幾個(gè)category范圍之外。
data
一個(gè)intent-filter里面可以有任意數(shù)量的data,一個(gè)intent只能攜帶一個(gè)data(和type),我們認(rèn)為,只要intent的data,完全符合intent-filter里面的任意一個(gè)data,就被認(rèn)為是匹配的。
<data
android:host="sdcard"
android:mimeType="video/mp4"
android:path="/sdcard/1.MP4"
android:pathPattern=".*\\.mp4"
android:pathPrefix="/sdcard/"
android:port="-2"
android:scheme="file" />
data的結(jié)構(gòu)里面主要包含了兩個(gè)東西,mimeType和URI。
mimeType
mimeType是指媒體類型,是一個(gè)區(qū)分大小寫(xiě)的字符串。比如image/jpeg,video/mpeg等等。
URI
URI由許多元素組成,下面是URI的結(jié)構(gòu):
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
具體的,比如:
file://sdcard/1.mp4
http://www.itdecent.cn/p/0321f33dff7f
- scheme
例如http、content、file。 - host
URI的主機(jī)名,比如www.itdecent.cn。 - port
端口號(hào)。 - path/pathPattern/pathPrefix
path表示完整的路徑。pathPattern是判定完整路徑是否匹配用的正則表達(dá)式。pathPrefix也是正則表達(dá)式,它匹配的是路徑的前綴信息。
匹配規(guī)則
intent的data完全符合intent-filter的data,意味著
- 默認(rèn)的URI
當(dāng)data當(dāng)中沒(méi)有配置任何的關(guān)于URI的參數(shù)的時(shí)候,scheme默認(rèn)為file或者content。
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/mp4" />
<data android:mimeType="image/*" />
</intent-filter>
上面的這段代碼的作用是:當(dāng)前的Activity可以用于打開(kāi)MP4,或者是任意圖片。如果你有興趣可以去試一下,當(dāng)你點(diǎn)擊打開(kāi)一張圖片的時(shí)候,系統(tǒng)會(huì)彈出多個(gè)應(yīng)用讓你來(lái)選擇用哪個(gè)應(yīng)用來(lái)打開(kāi)這張圖片,這時(shí)候除了系統(tǒng)自帶的相冊(cè),我們的應(yīng)用也會(huì)赫然出現(xiàn)在列表中。
intent.setDataAndType(Uri.parse("file://sdcard/1.mp4"), "video/mp4");
intent.setDataAndType(Uri.parse("file://sdcard/1.jpeg"), "image/jpeg");
這是啟動(dòng)目標(biāo)Activity的intent的配置方法。
隱式意圖匹配失敗的處理
隱式意圖一個(gè)很大的問(wèn)題就是我們并不知道系統(tǒng)里面是否有Activity能被匹配,比如如果你的手機(jī)里面一個(gè)查看圖片的Activity都沒(méi)有,那么用相應(yīng)的intent隱式啟動(dòng)注定會(huì)失敗并且拋出異常。所以在實(shí)際啟動(dòng)activity之前,最好是先做一下判斷,比如:
intent.resolveActivity(getPackageManager());
如果返回的是null,則表示匹配失敗,否則會(huì)返回最佳匹配的Activity。除此之外我們還有一種方法,可以返回所有成功匹配的Activity,像這樣:
getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
getPackageManager().queryIntentActivities(intent, PackageManager.GET_INTENT_FILTERS);
getPackageManager().queryIntentActivities(intent, PackageManager.GET_RESOLVED_FILTER);
最后說(shuō)一下一類特殊的intent-filter
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
它們組合出現(xiàn)代表程序會(huì)出現(xiàn)在系統(tǒng)的應(yīng)用列表中,單獨(dú)出現(xiàn)沒(méi)有任何意義。如果想獲得所有出現(xiàn)在應(yīng)用列表中的應(yīng)用,那么可以定義一個(gè)intent,用queryIntentActivities來(lái)獲取到匹配的所有Activit