IntentFilter
,顧名思義,就是Intent
的過濾器淤井∠倭溃回想一下捆昏,好像Intent
在我們的代碼中出現(xiàn)的頻率還是挺高的邓线,那么今天我們就來理理淌友。
Intent
Intent
的意思是意圖
, 而就和它的意思差不多骇陈,每當我們使用 Intent
的時候震庭, 總是去想干一些事情:
- startActivity(Intent intent)
- startService(Intent intent)
- bindService(Intent intent)
- sendBrodcast(Intent intent)
- .......
對的,我們再很多地方都會使用Intent
你雌。對于這些請求器联,我們都會傳入一個Intent
二汛,用來Filter
并啟動相應的Activity
、Service
拨拓、BroadcastReceiver
肴颊。而在這里,我們就有兩種調(diào)用方式:顯示調(diào)用和隱式調(diào)用渣磷。
顯式調(diào)用
就像啟動Activity
婿着,我們常常就是顯式的調(diào)用,那何為顯式調(diào)用呢醋界?
Intent itent = new Intent();
itent.setClass(Activity_A.this, Activity_B.class);
startActivity(itent);
哦竟宋,這就是顯式調(diào)用。之說以叫做顯式調(diào)用形纺,我們?yōu)?code>Intent清楚的指出了被啟動組件的信息(這里就是Activity_B
),當調(diào)用了startActivity(itent)
后丘侠,我們就只會很明確的知道,這次的任務是啟動Activity_B
,而沒有其它的過程逐样。
隱式調(diào)用
看了顯式調(diào)用蜗字,應該猜都猜得到了,隱式調(diào)用就是沒有明確的指出組件信息官研。而是通過Filter
去過濾出需要的組件秽澳。
Intent intent = new Intent();
intent.setAction(Intent.ACTION_BATTERY_LOW);
intent.addCategory(Intent.CATEGORY_APP_EMAIL);
intent.setDataAndType(Uri.EMPTY, "video/mpeg");
startActivity(intent);
這里就是一個隱式的調(diào)用,可以看到我為Intent
設置了三個屬性Action
戏羽、Category
担神、Data
。
然后startActivity(intent)
就會根據(jù)我們設置的這三個屬性去篩選合適的組件來打開始花,也就是因為這樣妄讯,所以有時候,當我們APP來分享一個東西的時候酷宵,會有很多組件(比如QQ亥贸、微信、微博...)來供我們選擇浇垦,因為他們都滿足Filter
條件炕置。或許你還有許多疑問男韧,來我們就接著來看IntentFilter
吧朴摊!
IntentFilter
IntentFilter
的意思就是意圖過濾器
,當我們隱式的啟動系統(tǒng)組件的時候,就會根據(jù)IntentFilter
來篩選出合適的進行啟動此虑。
現(xiàn)在我們知道了可以在Intent
啟動的時候對應設置Action
甚纲、Category
、DataAndType
,這里設置的是為了過濾的時候對應IntentFilter
匹配action
瀑踢、category
、data
抚垃。
除開過濾廣播的的IntentFilter
可以在代碼中創(chuàng)建外春哨,其它的IntentFilter
都得在AndroidManifest.xml
中給設置荆隘。
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
intentFilter.addCategory(Intent.CATEGORY_APP_EMAIL);
intentFilter.addDataType("video/mpeg");
Reciver reciver = new Reciver();
registerReceiver(reciver, intentFilter);
這里就是在代碼中設置IntentFilter
,可以看到我們設置了三個屬性。讓后我們再看看在AndroidManifest.xml
的設置方法:
<activity android:name=".Activity_B"
android:label="@string/title_activity_activity__b"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.ANSWER" />
<category android:name="android.intent.category.APP_EMAIL" />
<data android:host="www.mathiasluo.com"
android:scheme="http" />
</intent-filter>
</activity>
我們在這里給Activity
設置了一個IntentFilter
悲靴,但是值得注意的是臭胜,一個組件可以有多個IntentFilter
,在過濾的時候只要有一個符合要求的癞尚,就會被視為過濾通過耸三。
那我們就看看是怎樣過濾
的吧,首先我們應該明白一個大的思路:當我們隱式的啟動一個組件的時候,就會一個一個的去過濾對應組件的全部浇揩,(比如你是隱式的啟動一個Activity
仪壮,就會一個一個的在全部Activity
中篩選),然后根據(jù)Intent
的所設置的action
胳徽、category
积锅、data
去比較IntentFilter
所設置的這三個屬性,相同的話就過濾留下來了养盗。
action的匹配#####
action的匹配要求Intent中的action存在且必須和過濾規(guī)則中的其中一個action相同
首先缚陷,action
是一個字符串,匹配的話就是說兩個action
的字符串完全相同(Intent和IntentFilter中的action
)往核。然后我們就看看具體的匹配方法:
- 如果
IntentFilter
中有action箫爷,Intent
中必須有action -
Intent
中的action
必須在相應IntentFilter
中存在 -
Intent
中只需要有一個action
和IntentFilter
中相同即可
IntentFilter
中可以設置多個action
,Intent
中也可以設置多個action
,這里就是說我們Intent
中的action
必須存在IntentFilter
中聂儒,但是Intent
中不必包括IntentFilter
中全部的action
虎锚,但是至少包括一個。
category的匹配#####
category 要求Intent中可以沒有category衩婚,但是你一旦有category窜护,不管幾個,每個都要和IntentFilter中的category相同非春。
這里我們說Intent
中可以沒有category
,其實不然柱徙,只是在我們啟動組件(eg:startActivity( ))的時候,默認給我們的Intent
給加了一個category
("android.intent.category.DEFAULT" ).
哦奇昙,我們知道了這里坐搔,那么匹配就和action
差不多了,就是我們的Intent
中的category
必須在IntentFilter
中存在敬矩。這里得注意,Intent
中都會包括默認的category
,并且如果你想隱式啟動某個組件蠢挡,那么就得在IntentFilter中添加android.intent.category.DEFAULT
這個category
才行喲弧岳。
data的匹配#####
如果IntentFilter中有定義data凳忙,那么Intent中也必須也要定義可以的date
看了上面的兩個的匹配規(guī)則,發(fā)現(xiàn)其實還是很有規(guī)律的禽炬,對的涧卵,data
的匹配也差不多(其實我認為是一樣的,只是data
的結構要復雜些)腹尖。
<data android:mimeType="text/plain"
android:host="www.mathiasluo.com"
android:path="/myfolder/my.txt"
android:pathPattern="/myfolder/*"
android:port="80"
android:scheme="http" />
一看柳恐,嚇死,這么多热幔。
但其實一個data主要包括的就是一個URI和mimeType乐设。mimeType
就是媒體類型,就像"text/plain"
這樣的绎巨,可以表示data是圖片呀近尚、文本呀、視頻等等场勤。其它的就是URI
的了戈锻,簡單點,就是除開mimeType
和媳,剩下的全部都是屬于URI
的格遭,它們組成了URI
。而URI
中屬性就特別容易懂了留瞳,就像host
指的是主機名拒迅、Scheme
指的是URI
的模式、Port
指的端口號......
在Inten
中撼港,我們通過setDataAndType(Uri data, String type)
方法對date
進行設置坪它。這個方法接受兩個參數(shù),第一個就是URI
,第二個就是String
類型的mimeType
了帝牡,通過這一個方法往毡,我們就可以給Intent
設置data
了。靶溜、
隱式啟動的判斷
當我們隱式啟動的時候开瞭,獲取無法過濾找到所需要的組件,這樣的話就會報錯了罩息。那么有沒有什么方法來判斷隱式啟動的Intent
是否能找到相應的組件呢嗤详?
當然我們谷歌大法肯定是會知道我們的需求的。
Intent intent = new Intent();
intent.setAction(Intent.ACTION_BATTERY_LOW);
intent.addCategory(Intent.CATEGORY_APP_EMAIL);
intent.setDataAndType(Uri.EMPTY, "video/mpeg");
PackageManager packageManager = getPackageManager();
List<ResolveInfo> infoList = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
Log.i(TAG, infoList.size() + "");
if (infoList.size() != 0) {
startActivity(intent);
} else {
Log.e(TAG, "沒有匹配到Activity");
}
這里我們是通過PackageManager
來判斷的瓷炮,還有一種Intent
的方法:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_BATTERY_LOW);
intent.addCategory(Intent.CATEGORY_APP_EMAIL);
intent.setDataAndType(Uri.EMPTY, "video/mpeg");
ComponentName name = intent.resolveActivity(getPackageManager());
if (name != null){
startActivity(intent);
}else {
Log.e(TAG,"沒有匹配到Activity");
}
這兩個方法差不多葱色,也都很簡單,所以就不多說了娘香。
最后
還有苍狰,這些是我參考《Android開發(fā)藝術探索》的办龄,對,就是任大大的淋昭。