Android IntentFilter的匹配規則

IntentFilter中的過濾信息有action,category,data

匹配過濾列表,需要同時匹配過濾列表中的action、category、data信息,否則匹配失敗

action的匹配規則

action是一個字符串,系統預定義了一些action,同時我們也可以在應用中定義自己的action。action的匹配規則是Intent中action必須能夠和過濾規則中action匹配,這裏說的匹配是指action的字符串值完全一樣。一個過濾規則中可以有多個action,那麼只要Intent中的action能夠和過濾規則中的任何一個action相同即可匹配完成。需要注意的是,Intent中如果沒有指定action,那麼匹配失敗。總結:action的匹配要求Intent中的action存在且必須和過濾規則中的其中一個action相同。

 

category的匹配規則

category是一個字符串,系統預定義了一些category,同時我們也可以在應用中定義自己的category。category的匹配規則和action不同,它要求Intent中如果含有category,那麼所有的category都必須和過濾規則中的其中一個category相同。不設置category時也可以。因爲系統在startActivity或者startActivityForResult的時候會默認爲Intent加上“android.intent.category.DEFAULT”這個category。所以爲了我們的Activity能夠接受隱式調用,必須在intent-filter中指定“android.intent.category.DEFAULT”這個category。

 

data的匹配規則

 

data的匹配規則和action類似,如果過濾規則中定義了data,那麼Intent中必須定義可匹配的data。

data的結構:

<data android:scheme="string"

android:host="string"

android:port="string"

android:path="string"

android:pathPattern="string"

android:pathPrefix="string"

android:mimeType="string"/>

data由兩部分組成,mimeType和URI。mimeType指媒體類型,比如image/jpeg、audio/mpeg4-generic和video/*等,可以表示圖片、文本、視頻等不同的媒體格式。而URI中包含的數據比較多,其結構如下:

<scheme>://<host>:<port>/[<path>|pathPrefix>|<pathPattern>]

實際例子如:

content://com.example.project:200/folder/

http://www.baidu.com:80/serach

scheme:URI的模式,比如http、file、content等,如果沒有指定scheme,那麼整個URI的其它參數無效,即URI無效

host:URI的主機,如果沒有指定host,那麼整個URI的其它參數無效,即URI無效

port:URI的端口號,僅當URI中指定了scheme和host時參數纔有意義

path、pathPrefix、pathPattern:這三個參數表述路徑信息。其中path表示完整的路徑信息;pathPattern也表示完整的路徑信息,但是它裏面可以包含通配符“*”,“*”表示0個或者多個任意字符,需要注意的是,由於正則表達式的規範,如果想表示真實的字符串,那麼“*”要寫成“\\*”, "\" 要寫成"\\\\";pathPrefix表示路徑的前綴信息

 

1)如下過濾規則:

<intent-filer>

    <data android:mimeType="image/*"/>

    ....

</intent-filter>

這種規則指定了媒體類型爲所有類型的圖片,那麼Intent中的mimeType屬性必須爲“image/*”才能匹配,這種情況下雖然過濾規則沒有指定URI,但是卻有默認值,URI默認值爲content和file。也就是說沒有指定URI,但是Intent中的URI部分的scheme部分必須爲content或者file才能匹配,爲了匹配1)的規則,我們可以寫出如下示例:

intent.setDataAndType(Uri.parse("file://abc"),"image/png")

另外,如果要爲Intent指定完整的data,必須要調用setDataAndType方法,不能先調用setData再調用setType,因爲這兩個方法彼此會清除對方的值,源碼如下:

public @NonNull Intent setData(@Nullable Uri data) {
        mData = data;
        mType = null;
        return this;
    }

public @NonNull Intent setType(@Nullable String type) {
        mData = null;
        mType = type;
        return this;
    }

可以發現,這兩個方法會清除對方的值

2)如下過濾規則

<intent-filter>

    <data android:mimeType="video/mpeg" android:scheme="http"....../>

    <data android:mimeType="audio/mpeg" android:scheme="http"....../>

</intent-filter>

這種規則指定了兩組data規則,且每個data都指定了完整的屬性值,基友URI,又有mimeType。爲了匹配2)中規則,我們可以寫出以下示例:

intent.setDataAndType(Uri.parse("http://abc"),"video/mepg")

或者

intent.setDataAndType(Uri.parse("http://abc"),"audio/mepg")

 

通過上面兩個示例,我們已經明白了data的匹配規則,關於data還有一個特殊情況需要說明,這也是它和action不同的地方,以下兩種特殊的寫法,它們的作用是一樣的:

<intent-filter>

    <data android:scheme="file" android:host="www.baidu.com"/>

</intent-filter>

<intent-filter>

    <data android:scheme="file" />

    <data android:host="www.baidu.com"/>

</intent-filter>

data的匹配規則就是以上這些了。

最後,當我們通過隱式啓動一個Activity的時候,可以做一下判斷,看是否有Activity能夠匹配我們的隱式Intent,如果不做判斷,匹配不到時會報Activity找不到的錯誤。判斷方法有兩種:採用PackageManager的resolveActivity方法,或者Intent的resolveActivity方法,如果它們找不到匹配的Activity就會返回null,我們通過判斷返回值就可以避免找不到Activity的錯誤。另外PackageManager還提供queryIntentActivities方法,這個方法和resolveActivity不同的是:它不是返回最佳匹配的Activity信息,而是返回所有成功匹配的Activity信息

public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
            @ResolveInfoFlags int flags);

public abstract ResolveInfo resolveActivity(Intent intent, @ResolveInfoFlags int flags);

第二個參數需要注意,我們要使用MATCH_DEFAULT_ONLY這個標記位,這個標記位的含義是緊緊匹配哪些在intent-filter中聲明瞭“android.intent.category.DEFAULT”這個category的Activity。使用這個標記位的意義在於,只要商戶兩個方法不會null,那麼startActivity一定可以成功,如果不用這個標記位,那就把intent-filter中category不含有DEFAULT的哪些Activity給匹配出來,從而導致startActivity可能失敗。以爲不含有DEFAULT這個category的Activity是無法接收隱式Intent的。

 

在action和category中,有一類比較重要,他們是

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

這二者共同作用是用來表明這是一個入口Activity並且會出現在系統的應用列表中,少了任何一個都沒有實際意義,也無法出現在系統的應用列表中,也就是二者缺一不可。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章