【Android - 組件】之IntentFilter的匹配規則


  我們知道,Activity的啟動模式分為兩種,分別是顯式啟動和隱式啟動。顯式啟動需要明確的指定被啟動的對象的組件信息,包括包名和類名;而隱式啟動需要 Intent 能夠匹配目標組件的 IntentFilter 中所設置的過濾信息(原則上,一個Intent不應該既是顯式調用又是隱式調用,如果二者共存,則顯示調用為主)。

  IntentFilter 中的過濾信息包括 action、category 和 data。為了匹配過濾列表,需要同時匹配過濾列表中的action、category和data信息,否則匹配失敗。一個Activity中可以有多個IntentFilter,一個Intent只要能匹配任何一組 intent-filter,即可成功啟動對應的Activity。以下是一個過濾規則的實例:

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="my.itgungnir.action1" />
        <category android:name="my.itgungnir.category1" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="my.itgungnir.action2" />
        <action android:name="my.itgungnir.action3" />
        <category android:name="my.itgungnir.category2" />
        <category android:name="my.itgungnir.category3" />
        <category android:name="my.itgungnir.category4" />
        <data android:mimeType="text/plain" />
        <data android:host="www.baidu.com" />
    </intent-filter>
</activity>

 

action的匹配規則

  action是一個字符串。action的匹配規則是:Intent中必須有一個action且必須能夠和過濾規則中的某個action匹配(這里說的匹配是指字符串值完全一樣)。

  【注意】

    • action中的內容是區分大小寫的;
    • Intent中如果沒有指定action,則視為匹配失敗。

 

category的匹配規則

  category是一個字符串。category的匹配規則是:Intent中可以沒有category,但是如果一旦有category,不管有幾個,每個都要能夠和過濾規則中的任何一個category匹配。

  【注意】:如果想讓Activity A隱式啟動Activity B,那么需要在Activity B的 intent-filter 中指定 android.intent.category.DEFAULT 這個category,原因是系統在調用 startActivity() 或者 startActivityForResult() 方法的時候會默認為Intent加上 android.intent.category.DEFAULT 這個category。

 

data的匹配規則

  data的匹配規則:Intent中必須含有data數據,並且data數據能夠完全匹配過濾規則中的某一個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 ,URI通過如下格式,包括scheme、host、port、path、pathPrefix和pathPattern。

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

  具體的參數解釋如下:

   mimeType :指媒體類型,比如 image/jpeg、audio/mpeg4-generic、vidio/*等,可以表示圖片、文本、視頻等不同的媒體格式。

   scheme :URI的模式,如http、file、content等,如果URI中沒有指定scheme,那么整個URI的其他參數無效,這也意味着URI是無效的。

   host :URI的主機名,如www.baidu.com,如果host未指定,那么整個URI中的其他參數無效,這也意味着URI是無效的。

   port :URI中的端口號,比如80,進檔URI中指定了scheme和host參數的時候,port參數才是有意義的。

   path :表述路徑的完整信息。

   pathPrefix :表述路徑的前綴信息。

   pathPattern :表述路徑的完整信息,但它里面可以包含通配符 * ,表示0個或任意字符(如果想要表示真是字符串,則需要轉義成 \\* ; \ 要寫成 \\\\ )。

  我們可以通過 intent.setDataAndType(Uri.parse("URI字符串"), "mimeType字符串") 的格式為Intent設置data。

  【注意】

    • URI可以不設置,但如果設置了,則 scheme 和 host 屬性必須要設置;
    • URI的 scheme 屬性有默認值,默認值為 content 或者 file ,因此,就算在 intent-filter 中沒有為data設置URI,也需要在匹配的時候設置scheme和host兩個屬性,且scheme屬性的值必須是content或者file;
    • 在為Intent指定data的時候,必須要調用 setDataAndType() 方法,不能先調用 setData() 再調用 setType() ,因為這兩個方法會彼此清楚對方的值;
    • 所有有關data的屬性可以放在同一個<data>標簽中,也可以分作多個<data>標簽存放,其效果相同。

 

總結

1、以下是在JAVA代碼中匹配某個Activity的 intent-filter 的代碼:

Intent intent = new Intent();
intent.addAction("my.itgungnir.action1");
intent.addCategory("my.itgungnir.category1");
intent.setDataAndType(Uri.parse("file://abc"), "text/plain");
startActivity(intent);

2、在Menifest文件的<intent-filter>標簽中,action、category和data都可以有多個;在JAVA代碼中,一個Intent中只能有一個action和一個data,可以有多個category。

3、我們在通過隱式方式啟動一個Activity的時候,可以做以下判斷,看有沒有Activity能夠匹配我們的Intent,具體的判斷方法有兩種:

 (1)使用 PackageManager 或者 Intent 的 resolveActivity() 方法,這個方法會返回最佳匹配的Activity信息,如果沒有匹配的Activity,則返回null;

 (2)使用 PackageManager 的 queryIntentActivities() 方法,這個方法會返回所有成功匹配的Activity的信息。

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

  需要說明的是這兩個方法的第二個參數,我們在使用這兩個方法的時候,第二個參數都必須是 Intent.MATCH_DEFAULT_ONLY ,這個參數用來匹配那些在 intent-filter 中聲明了category為 android.intent.category.DEFAULT 的Activity,避免某些Activity因為沒有設置category為DEFAULT而無法接收隱式Intent。

4、如果想將一個Activity標記為應用的入口,可以在其 <intent-filter> 標簽中添加如下兩行屬性(這兩行屬性必須同時存在才有用,缺一不可):

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM