IntentFilter匹配規(guī)則

IntentFilter直譯過(guò)來(lái)就是意圖過(guò)濾器,我們可以通過(guò)它的匹配規(guī)則去打開我們想要打開的一類Activity,例如我們想要打開手機(jī)瀏覽器,但是我們不知道用戶安裝了哪些瀏覽器或者習(xí)慣于使用哪個(gè)瀏覽器,那么我們就可以通過(guò)IntentFilter來(lái)啟動(dòng),讓用戶自己選擇使用哪個(gè)瀏覽器。
IntentFilter可以在AndroidManifest.xml中注冊(cè)Activity時(shí)通過(guò)<intent-filter>標(biāo)簽來(lái)設(shè)置intentFilter,它有3個(gè)標(biāo)簽屬性action,categorydata。

<activity
  android:launchMode="standard"
  android:name=".MainActivity">
  <intent-filter>
       <action android:name="android.intent.action.MAIN" />

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

在說(shuō)intentFilter的匹配規(guī)則前,有必要得先講一下Activity的調(diào)用模式,注意是調(diào)用模式而不是啟動(dòng)模式。Activity的調(diào)用模式有兩種:顯式調(diào)用隱式調(diào)用

  • 顯式調(diào)用
    大多數(shù)情況下我們最常接觸到的就是顯式調(diào)用了:
Intent intent = new Intent(FirstActivity.this,SecondActivity.class); 
startActivity(intent);

其實(shí)嚴(yán)格來(lái)講,這個(gè)也不算是顯式調(diào)用,因?yàn)樵陲@式調(diào)用的意義中需要明確之處被啟動(dòng)的對(duì)象的組件信息,包括包名和類名,這里并沒(méi)有之處包名:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName("com.mg.axe.testappa","com.mg.axe.testappa.MainActivity");
intent.setComponent(cn);
startActivity(intent);  
  • 隱式調(diào)用
    需要Intent能匹配目標(biāo)組件的IntentFilter中所設(shè)置的過(guò)濾信息.如果不匹配將無(wú)法啟動(dòng)目標(biāo)Activity。
    示例:
Intent intent = new Intent(); 
intent.setAction("android.intent.action.View"); 
startActivity(intent);

當(dāng)我們進(jìn)行Activity的隱式調(diào)用時(shí),IntentFilter就可以排上用場(chǎng)了,那么下面將詳細(xì)介紹其匹配規(guī)則:

  • Action的匹配規(guī)則
    Intent中的action必須能夠和Activity過(guò)濾規(guī)則中的Action完全匹配(即完全相等)。一個(gè)過(guò)濾規(guī)則中有多個(gè)action,那么只要Intent中的action能夠和Activity過(guò)濾規(guī)則中的任何一個(gè)action相同即可匹配成功。簡(jiǎn)單的說(shuō)就是Intent中的action必須出現(xiàn)在目標(biāo)Activity的過(guò)濾規(guī)則中。
    示例:
<!--SecondActivity的intent-filter-->
<intent-filter>
 <category android:name = "android.intent.category.DEFAULT" />
 <action android:name="com.axe.mg.what" />
</intent-filter>

<!--ThirdActivity的intent-filter-->
<intent-filter>
 <category android:name = "android.intent.category.DEFAULT" />
 <action android:name="com.axe.mg.what" />
 <action android:name="com.axe.mg.how"/>
</intent-filter>

<!--FourthActivity的intent-filter-->
<intent-filter>
 <category android:name = "android.intent.category.DEFAULT" />
 <action android:name="com.axe.mg.why" />
 <action android:name="com.axe.mg.how"/>
</intent-filter>
Intent intent = new Intent();
intent.setAction("com.axe.mg.what");
startActivity(intent);

這種啟動(dòng)方式既可以啟動(dòng)SecondActivity,也可以啟動(dòng)ThirdActivity,但是無(wú)法啟動(dòng)FourthActivity。且必須至少含有一個(gè)<category android:name = "android.intent.category.DEFAULT" />標(biāo)簽,否則系統(tǒng)會(huì)拋出ActivityNotFoundException的異常

  • category的匹配規(guī)則
    一個(gè)Intent可以設(shè)置多個(gè)category,且Intent中的所有category都必須匹配到Activity中。也可以不設(shè)置category,這時(shí)系統(tǒng)會(huì)自動(dòng)匹配android.intent.category.DEFAULT。這里可能感覺(jué)和action很像,但是只要稍微注意一下就可以發(fā)現(xiàn)Intent是setActionaddCategory,也就是說(shuō)action只有一個(gè)(注意是一個(gè)Intent只有一個(gè)action,但是一個(gè)Activity的intent-filter中可以有多個(gè)action),而category可以有很多個(gè)且所有的category都必須出現(xiàn)在Activity的category集中。
    示例:
<!--SecondActivity的intent-filter-->
<intent-filter>
 <action android:name="com.axe.mg.what" />
 <category android:name="com.yu.hu.category1"/>
 <category android:name="com.yu.hu.category2"/>
 <category android:name = "android.intent.category.DEFAULT" />
</intent-filter>

<!--ThirdActivity的intent-filter-->
<intent-filter>
 <action android:name="com.axe.mg.what" />
 <category android:name = "android.intent.category.DEFAULT" />
 <category android:name="com.yu.hu.category1"/>
 <category android:name="com.yu.hu.category2"/>
 <category android:name="com.yu.hu.category3"/>
</intent-filter>

<!--FourthActivity的intent-filter-->
<intent-filter>
 <action android:name="com.axe.mg.what" />
 <category android:name = "android.intent.category.DEFAULT" />
 <category android:name="com.yu.hu.category2"/>
</intent-filter>
Intent intent = new Intent();
intent.addCategory("com.yu.hu.category1");
intent.addCategory("com.yu.hu.category2");
intent.setAction("com.yu.hu.what");
startActivity(intent);

此時(shí)依然只能匹配到前兩個(gè)Activity,因?yàn)镕ourthActivity沒(méi)有category1。


另外這里還有兩點(diǎn)要注意

  1. 因?yàn)閺?qiáng)制要求一個(gè)Activity需要一個(gè)<category android:name="android.intent.category.DEFAULT"/>,所以我們不用將這個(gè)categoty添加到intent中去匹配。
  2. 如果單獨(dú)只addCategory是沒(méi)有用的,必須setAction之后才行。
  • data的匹配規(guī)則
    首先來(lái)說(shuō)一下data的結(jié)構(gòu),data由兩部分組成:mineTypeURI。mineType指媒體類型,如.png .jpg等。而URI可配置更多信息:
  • scheme:URI的模式,如http。如果URI中沒(méi)有指定scheme,那么整個(gè)URI無(wú)效。默認(rèn)為contentfile
  • host:URI的host(域名、網(wǎng)址),如www.baidu.com。如果指定了schemeport,path等其他參數(shù),但是host未指定,那么整個(gè)URI無(wú)效;如果只指定了scheme,沒(méi)有指定host和其他參數(shù),URI是有效的。
  • port:URI端口,當(dāng)URI指定了schemehost 參數(shù)時(shí)port參數(shù)才有意義。
  • path:用來(lái)匹配完整的路徑,如:http://example.com/blog/abc.html,這里將 path 設(shè)置為 /blog/abc.html 才能夠進(jìn)行匹配;
  • pathPrefix:用來(lái)匹配路徑的開頭部分,拿上面的 URI 來(lái)說(shuō),這里將pathPrefix設(shè)置為 /blog 就能進(jìn)行匹配了;
  • pathPattern:用表達(dá)式來(lái)匹配整個(gè)路徑。

總的來(lái)說(shuō)有點(diǎn)像是正則表達(dá)式,用于匹配指定字段內(nèi)容。
示例:假如我想要匹配https://www.baidu.com:8080/imgs/*,那么data應(yīng)該這么寫:

<intent-filter>
   <action android:name="xx" />
   <category android:name="android.intent.category.DEFAULT" />
   <data
     android:host="www.baidu.com"
     android:pathPrefix="/imgs"
     android:port="8080"
     android:scheme="https" />
 </intent-filter>

java代碼:

  Intent intent = new Intent();
  intent.setData(Uri.parse("https://www.baidu.com:8080/imgs/img1.png"));
  startActivity(intent);

推薦閱讀:intent-filter的action,category,data匹配規(guī)則

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容