文章目錄
- 一、什么是IntentFilter ?
- 二、IntentFilter 如何過濾隱式意圖?
- 2.1 動作測試
- 2.2 類別測試
- 2.3 數據測試
一、什么是IntentFilter ?
如果一個 Intent 請求在一片數據上執行一個動作, Android 如何知道哪個應用程序(和組件)能用來響應這個請求呢?
IntentFilter
就是用來注冊 Activity
、 Service
和 Broadcast Receiver
具有能在某種數據上執行一個動作的能力。
使用 IntentFilter
,應用程序組件告訴 Android ,它們能為其它程序的組件的動作請求提供服務,包括同一個程序的組件、本地的或第三方的應用程序。
IntentFilter
翻譯成中文就是“意圖過濾器”,主要用來過濾隱式意圖。當用戶進行一項操作的時候,Android系統會根據配置的 “意圖過濾器” 來尋找可以響應該操作的組件,服務。
例如:當用戶點擊PDF文件的時候,Android系統就會通過設定好的意圖過濾器,進行匹配測試。找到能夠打開PDF文件的APP程序。
代碼:
<activity android:name="com.example.testmain.ShowActivity" ><intent-filter><action android:name="test.update.mydata" /><category android:name="my.test.show" /><data android:pathPattern=".*\\.jpg" android:scheme="http" /></intent-filter>
</activity>
二、IntentFilter 如何過濾隱式意圖?
Android
系統會根據配置的Intent Filter(意圖過濾器),來進行匹配測試。匹配的時候,只會考慮三個方面:動作、數據(URI以及數據類型)和類別。也就是說Android
系統會進行“動作測試”,“數據測試”,“類別測試”,來尋找可以響應隱式意圖的組件或服務。
另外,當對其他App程序開放組件和服務的時候也需要配置Intent Filter(意圖過濾器),一個Activity可以配置多個<intent-filter>
。
2.1 動作測試
對應<intent-filter>
中的<action/>
標簽;
-
如果
<intent-filter>
標簽中有多個<action/>
,那么Intent
請求的Action
,只要匹配其中的一條<action/>
就可以通過了這條<intent-filter>
的動作測試。 -
如果
<intent-filter>
中沒有包含任何<action/>
,那么無論什么Intent
請求都無法和這條<intent-filter>
匹配。 -
如果
Intent
請求中沒有設定Action
(動作),那么這個Intent
請求就將順利地通過<intent-filter>
的動作測試(前提是<intent-filter>
中必須包含有<action/>
,否則與第二條沖突)。
2.2 類別測試
對應<intent-filter>
中的<category />
標簽;
Intent
中的類別必須全部匹配<intent-filter>
中的<category />
,但是<intent-filter>
中多余的<category />
將不會導致匹配失敗。
例如:Intent中有3個類別,而意圖過濾器中定義了5個,如果Intent中的3個類別都與過濾器中的匹配,那么過濾器中的另外2個,將不會導致類別測試失敗。
注意:有一個例外,Android
把所有傳給startActivity()
的隱式意圖當作他們包含至少一個類別:“android.intent.category.DEFAULT
” (CATEGORY_DEFAULT
常量)。 因此,想要接收隱式意圖的活動必須在它們的意圖過濾器中包含"android.intent.category.DEFAULT
"。(帶"android.intent.action.MAIN
"和"android.intent.category.LAUNCHER
"設置的過濾器是例外)
2.3 數據測試
對應<intent-filter>
中的<data>
標簽;
<data>
元素指定了可以接受的Intent
傳過來的數據URI和數據類型,當一個意圖對象中的URI被用來和一個過濾器中的URI比較時,比較的是URI的各個組成部分。
例如:
如果過濾器僅指定了一個scheme
,所有該scheme
的URIs
都能夠和這個過濾器相匹配;
如果過濾器指定了一個scheme
、主機名但沒有路經部分,所有具有相同scheme
和主機名的URIs都可以和這個過濾器相匹配,而不管它們的路經;
如果過濾器指定了一個scheme
、主機名和路經,只有具有相同scheme、主機名和路經的URIs才可以和這個過濾器相匹配。當然,一個過濾器中的路徑規格可以包含通配符,這樣只需要部分匹配即可。
比較規則如下:
-
一個既不包含URI也不包含數據類型的意圖對象,僅在過濾器也同樣沒有指定任何URI和數據類型的情況下才能通過測試。
-
一個包含URI但沒有數據類型的意圖對象,僅在它的URI和一個同樣沒有指定數據類型的,過濾器里的URI匹配時才能通過測試。這通常發生在類似于mailto:和tel:這樣的URIs上:它們并不引用實際數據。
-
一個包含數據類型但不包含URI的意圖對象,僅在這個過濾器列舉了同樣的數據類型,而且也沒有指定一個URI的情況下才能通過測試。
-
一個同時包含URI和數據類型(或者可從URI推斷出數據類型)的意圖對象可以通過測試,如果它的類型和過濾器中列舉的類型相匹配的話。如果它的URI和這個過濾器中的一個URI相匹配或者它有一個內容
content:
或者文件file: URI
,而且這個過濾器沒有指定一個URI,那么它也能通過測試。換句話說,一個組件被假定為支持”content: 數據“ 和 “file: 數據”,如果它的過濾器僅列舉了一個數據類型。
例如AndroidManifest.xml
(AndroidManifest.xml
是安卓開發中主配置文件,程序執行首先瀏覽這個文件的內容)中有:
對于<intent-filter>
中的action
項可以有多個只要匹配其中一個就可以了
intent.setAction("com.nanlove.wangshiming");//中的action也可以為wangshimingintent.addCategory("wangshiming.intent.category")// 代碼中的addCategory并不用寫因為android他有默認的category 只要配置清單中存在<category android:name="android.intent.category.DEFAULT" />就可以了.
沒有 “數據參數” 的情況下只要意圖對象中的設置動作和類別都出現在intent-filter
就能跟filter匹配,但是有數據<data android:scheme="love" android:host="hao123.com" android:port="888" android:path="/MM" />
數據項一定要完全匹配。
當數據和數據類型 android:mimeType="text/plain"
同時存在的時候,不能使用intent.setData(Uri.parse("love://hao123.com:888/MM")) ;
因為setData
的方法會自動清除前面的數據類型:This method automatically clears any type that was previously set by setType;
所以后面的setType
就無法匹配,應該使用intent.setDataAndType(Uri.parse("love://hao123.com:888/MM"), "text/plain");
提示:在同一個應用內,能使用顯示意圖,就盡量使用顯示意圖,增加程序的效率,理論上隱式意圖匹配規則是需要花時間尋找的。