1. 程式人生 > >Android IntentFilter的匹配規則

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並且會出現在系統的應用列表中,少了任何一個都沒有實際意義,也無法出現在系統的應用列表中,也就是二者缺一不可。