intentFiltger的匹配原則

weixin_33797791發表於2017-11-20

關於intentFiltger的匹配原則,action和category就不具體描述了,相信大家也有基本的瞭解的,就概括說一下就行了,這篇文章主要講述data的匹配原則,當然是以隱式跳轉的主題講解的。

1. action的匹配原則

action的匹配原則要求Intent中的action存在並且必須和過濾器規則中其中一個action相同,另外,action區分大小寫。否則匹配失敗。

2. category匹配原則

(1)如果不存在category,系統預設使用android:intent.category.DEFAULT,隱式跳轉除外。如果要使用隱式跳轉,必須在intent-filter裡邊制定這個屬性。
(2) 如果存在,intent跳轉中一旦有category,不管有幾個,每個都需要能夠和過濾規則中的任何一個category相同。使用addcategroy方法。可以多個category和intent-filter中的一個相同。

3. 說下action和category的不同點吧

action:intent中必須存在一個action,並且必須有一個action和過濾規則中的action相同。
category:intent中可以不存在category,但是一旦存在,那麼所有的category都必須和過濾規則中的其中一個category相同。

————————————————我是分割線—————————————

好了 下邊進入主題。data的匹配原則。

1. 先來看下data的用法

<data android:scheme="String"
     android:host="String"
     android:path="String"
     android:pathPattern="String"
     android:pathPrefix="String"
     android:mimeType="String"></data>

data由兩部分組成,mimeType和URI組成。mimeType代表媒體型別,比如image/aaa.jpg等。URI表示路徑。下邊來講解下每個資料的含義。
(1) Scheme:URI模式,比如http、filem、content等,如果URI中沒有制定Scheme,那麼整個URI的其他引數無效,這也就意味著整個URI無效。
(2) Host:URI的主機名,比如www./baidu.com,如果host為制定,整個URI中其他的引數無效,這也就意味著整個URI無效。
(3) Port:URI中的的埠號,比如80埠,僅當scheme和host引數制定的時候,port引數才是有意義的。
(4) path:表示完成的路徑資訊。
(5) pathPattern:也表示完成的路徑資訊,但他可以包含萬用字元“ * ”,* 表示 0個或者多個任意字元,需要注意的是,由於正則的規範,如果想表示真實的字元,要攜程\, \要寫成\\,
(6) pathPrefix:表示路徑的字首資訊。

2. 分情況說明下匹配原則

(1) 程式碼如下:

<intent-filter>
      <data android:mimeType="image/*"
           ...  
</intent-filter>  

這種規則指定了媒體型別為所有型別的圖片,那麼intent中的mimeType必須為image/*才能匹配,這種情況下規律雖然沒有指定URI,但是卻又預設值,URI的預設值是content和file。也就是說雖然沒有指定URI,但是intent的URI部分的scheme必須為content和file才能匹配。也可以這樣寫:
intent.setDataAndType(Uri.parse("file://abc"), "image/aaa");
這裡需要注意的是必須呼叫setDataAndType,不能先呼叫setData然後呼叫setType,這兩個方法會清除對方的值,來看下原始碼:

public Intent setData(Uri data) {
     mData = data;
     mType = null;
     return this;
}
public Intent setType(String type) {
     mData = null;
     mType = type;
     return this;
}

setData會把mimeType置空,setType會把URI置空。

(2) 程式碼如下:

<intent-filter>
     <data android:scheme="http" android:mimeType="video/aaa" ...></data>
     <data android:scheme="http" android:mimeType="video/bbb" ...></data>
</intent-filter>

剩下的我想你們應該也會寫了,我就不寫了。

(3) 寫兩種程式碼,作用其實是一樣的。

<intent-filter>
<data android:scheme="http" android:mimeType="video/aaa" ></data> 
     ...
</intent-filter>

<intent-filter>
     <data android:scheme="http" ></data>
     <data android:mimeType="video/aaa" ></data>
     ...
</intent-filter>

————————————————我是分割線—————————————

好了,關於intentFiltger的匹配原則就先說到這裡,相信大家已經有了基本的認識了,來說寫題外話吧。關於Activity跳轉到Service或者BroadCastReceiver同樣可以使用隱式跳轉,不過系統對於啟動Ssrvice的建議還是使用顯示跳轉方法來啟動服務。

我再囉嗦一點哈,你們不要打我。

PS:這點很重要

PS:這點很重要

PS:這點很重要

重要的事情說三遍。

當我們使用隱式跳轉啟動一個Activity的時候,可以做一下判斷,看是否有Activity能匹配我們的隱式Intent.如果不能就會出現ActivityNotFoundException錯誤了。判斷方法有兩種,如果找不到匹配的Activity,則返回null:

1. PackageManager.resolveActivity():

使用PackageManager的resolveActivity方法,並且PackageManager還提供了queryIntentActivites方法,這個方法和resolveActivity不同的是,它不是返回的最佳的Activity,而是返回了所有匹配成功的Activity。原始碼:
public abstract List<ResolveInfo> queryIntentActivities(Intent intent, int flags);
public abstract ResolveInfo resolveActivity(Intent intent, int flags);
第一個引數比較好理解,第二個引數需要注意,我們需要使用MATCH_DEFAULT_ONLY這個標記位,它的含義是陪陪那些在intent-filter中生命了category android:name="android.intent.category.DEFAULT"這個category的Activity,使用這個標記位的意義在於,只要上邊兩個方法不返回null,那麼startActivity一定可以成功,如果不用這個標記位,那就可以吧intent-filter中category不含DEFAULT的那些Activity匹配出來,從而導致startActivity可能失敗,因為不包含DEFAULT這個category的Activity是無法接收隱式Intent的,在action和category中,有一類action和category比較重要,也是大家最常見的:

<intent-filter>
     <action android:name="android.intent.action.MAIN" />
     <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

他們表明這是一個入口Activity並且出現在系統的應用列表中,少了任何一個都沒有實際的意義,也無法出現在系統的應用列表中,另外針對Service和BroadCastReceiver,PackageManager同樣提供了類似的方法獲取成功匹配的元件資訊。

2. 使用Intent的resolveActivity方法也是可以判斷的。

相關文章