當(dāng)前位置:首頁 > 芯聞號(hào) > 充電吧
[導(dǎo)讀]概述我們知道,Intent是分兩種的:顯式Intent和隱式Intent。如果一個(gè)Intent明確指定了要啟動(dòng)的組件的完整類名,那么這個(gè)Intent就是顯式Intent,否則就是隱式Intent。當(dāng)我

概述

我們知道,Intent是分兩種的:顯式Intent和隱式Intent。如果一個(gè)Intent明確指定了要啟動(dòng)的組件的完整類名,那么這個(gè)Intent就是顯式Intent,否則就是隱式Intent。當(dāng)我們用一個(gè)顯式Intent去啟動(dòng)組件時(shí),Android會(huì)根據(jù)Intent對(duì)象所提供的component name直接找到要啟動(dòng)的組件,當(dāng)我們用一個(gè)隱式的Intent去啟動(dòng)組件時(shí),Android系統(tǒng)就無法直接知道要啟動(dòng)的組件名稱了,本文就是講解Android系統(tǒng)如何根據(jù)隱式Intent查找匹配到要啟動(dòng)的組件。

當(dāng)Android系統(tǒng)接收到一個(gè)隱式Intent要啟動(dòng)一個(gè)Activity(或其他組件)時(shí),Android會(huì)根據(jù)以下三個(gè)信息比較Intent的信息與注冊(cè)的組件的intent-filter的信息,從而為該Intent選擇出最匹配的Activity(或其他組件):

intent中的action

intent中的category

intent中的data(包含Uri以及data的MIME類型)

也就是隱式intent對(duì)象要滿足要啟動(dòng)的目標(biāo)組件中注冊(cè)的intent-filter中的、、三個(gè)標(biāo)簽中的信息,即要分別通過action測(cè)試、category測(cè)試以及data測(cè)試。intent-filter信息是在Android的manife文件中描述的,顧名思義,intent-filter是intent過濾器,就是用來過濾intent的。

如果隱式intent對(duì)象同時(shí)通過了某個(gè)組件的中intent-filter的action測(cè)試、category測(cè)試以及data測(cè)試,那么該組件就可以被intent對(duì)象所啟動(dòng)。如果隱式intent對(duì)象沒有通過系統(tǒng)中任何組件的intent-filter測(cè)試,那么就沒有Android系統(tǒng)無法找到該intent對(duì)象要啟動(dòng)的組件。下面我們依次看一下如何才能通過這三個(gè)測(cè)試。

Action測(cè)試

為了指定能夠接收并處理的Intent的類型,組件可以在intent-filter中聲明其支持0個(gè)或多個(gè)action,例如:

intent對(duì)象可以通過setAction()方法設(shè)置唯一的一個(gè)action值。對(duì)于action測(cè)試,需要分兩種情況:

intent對(duì)象設(shè)置了action

如果intent對(duì)象通過調(diào)用setAction()方法設(shè)置了action的值,那么只有當(dāng)組件的intent-filter中包含了intent對(duì)象中的action值的時(shí)候,action測(cè)試才通過,否則無法通過。

舉個(gè)例子,假設(shè)我們的Activity的intent-filter如下所示:

下面的intent對(duì)象可以通過上面intent-filter里面的action測(cè)試:

Intent intent = new Intent();

intent.setAction("com.ispring.action.ACTION_TEST1");

Uri uri = Uri.parse("ispring://blog.csdn.net/sunqunsunqun");

intent.setData(uri);

該intent之所以能通過action測(cè)試是因?yàn)閕ntent-filter中包含該intent的action值com.ispring.action.ACTION_TEST1。

下面的intent對(duì)象無法通過上面intent-filter里面的action測(cè)試:

Intent intent = new Intent();

intent.setAction("com.ispring.action.ACTION_TEST3");

Uri uri = Uri.parse("ispring://blog.csdn.net/sunqunsunqun");

intent.setData(uri);

該intent之所以無法通過action測(cè)試是因?yàn)閕ntent-filter中不包含該intent的action值com.ispring.action.ACTION_TEST3。

intent對(duì)象沒有設(shè)置action

如果intent對(duì)象沒有調(diào)用setAction()方法設(shè)置action的值,那么如果intent-filter至少有一個(gè)任意的action的值,該intent對(duì)象就可以通過該intent-filter的action測(cè)試,反之,如果intent-filter中沒有定義任何的action,那么該intent無法通過該intent-filter的action測(cè)試。

舉個(gè)例子,假設(shè)我們的intent對(duì)象如下所示:

Intent intent = new Intent();

//不設(shè)置action值

//intent.setAction("com.ispring.action.ACTION_TEST1");

Uri uri = Uri.parse("ispring://blog.csdn.net/sunqunsunqun");

intent.setData(uri);

上面的intent對(duì)象可以通過如下的intent-filter:

上面的intent對(duì)象無法通過如下的intent-filter:

通過上面的幾個(gè)示例,想必大家都已經(jīng)理解了action測(cè)試的規(guī)則,至于上面的category和data標(biāo)簽的使用,會(huì)在下面詳細(xì)介紹。

總結(jié)起來有兩點(diǎn)結(jié)論:

1. 要想讓intent對(duì)象通過action測(cè)試,那么intent-filter中聲明的action不能為空且要包含intent對(duì)象中的action值(如果intent的action值不為空的話)。

2. 如果intent-filter沒有聲明任何action,那么所有的intent的對(duì)象(即無論intent如何配置)都無法通過intent-filter的action測(cè)試。

Category測(cè)試

為了指定能夠接收并處理的Intent的類型,組件可以在intent-filter中聲明其支持0個(gè)或多個(gè)category,例如:

...

intent對(duì)象有addCategory()方法,也就是說一個(gè)intent對(duì)象也可以關(guān)聯(lián)多個(gè)category。為了能讓intent對(duì)象通過intent-filter的category測(cè)試,intent對(duì)象中的所有category都要在intent-filter中找到對(duì)應(yīng)項(xiàng)。

具體來說,又分為如下兩種情況:

intent對(duì)象至少有一個(gè)category

這種情況下,假設(shè)intent對(duì)象有N個(gè)category(N >=1),那么intent-filter中必須要包含這N個(gè)category,intent對(duì)象才能通過category測(cè)試,否則無法通過測(cè)試。如果用intent對(duì)象啟動(dòng)Activity,還有其他限制條件,會(huì)在后面詳細(xì)說明。

舉個(gè)例子,假設(shè)我們的intent-filter如下所示:

以下intent對(duì)象能夠通過category測(cè)試

Intent intent = new Intent();

intent.setAction("com.ispring.action.ACTION_TEST1");

intent.addCategory("com.ispring.category.TEST1");

intent.addCategory("com.ispring.category.TEST2");

該intent對(duì)象之所以可以通過category測(cè)試是因?yàn)閕ntent-filter包含了該intent對(duì)中所有的category值:com.ispring.category.TEST1”和com.ispring.category.TEST2。

以下intent對(duì)象無法通過category測(cè)試

Intent intent = new Intent();

intent.setAction("com.ispring.action.ACTION_TEST1");

intent.addCategory("com.ispring.category.TEST1");

intent.addCategory("com.ispring.category.TEST3");

該intent之所以無法通過上面的intent-filter的category測(cè)試是因?yàn)閕ntent-filter只包含了該intent中值為com.ispring.category.TEST1的category,而并未包含值為com.ispring.category.TEST3的category,不滿足完全包含intent中全部category的情況。

intent對(duì)象不包含任何category

如果intent對(duì)象沒有調(diào)用過addCategory()方法,那么intent對(duì)象就不包含任何的category。這種情形下,如果該intent不是用來啟動(dòng)Activity的話,那么無論intent-filter中category中如何配置,intent對(duì)象總是能通過intent-filter的category測(cè)試,即便intent-filter中沒有聲明任何的category,intent都能通過category測(cè)試。此處強(qiáng)調(diào)了該intent不是用來啟動(dòng)Activity這種條件,會(huì)在下面詳細(xì)解釋。

此處需要特別說明的是,我們?cè)谏厦嫠械氖纠校冀oActivity的intent-filter添加了值為android.intent.category.DEFAULT的category,這是因?yàn)楫?dāng)我們把一個(gè)隱式的intent傳遞給startActivity()或startActivityForResult()方法時(shí),Android會(huì)自動(dòng)給該隱式intent添加值為android.intent.category.DEFAULT的category,所以為了能讓intent-filter包含intent中全部的category,我們就需要在Activity的intent-filter中添加該category,在使用時(shí)需要特別注意。

根據(jù)上面我們的幾個(gè)示例,我們總結(jié)如下:

1. 如果intent對(duì)象不包含任何category,并且該intent不是用來啟動(dòng)Activity的,那么該intent對(duì)象總是能通過所有任意的intent-filter的category測(cè)試;

2. 如果intent對(duì)象包含category(至少一個(gè)),那么只有當(dāng)intent-filter中聲明的category全部包含intent對(duì)象中的所有category的時(shí)候才通過category測(cè)試。

3. 如果允許Activity被隱式的Intent啟動(dòng),那么我們必須在該Activity的intent-filter中聲明值為android.intent.category.DEFAULT的category。

Data測(cè)試

為了指定可以接收的Intent的data,intent-filter需要聲明0個(gè)多多個(gè)標(biāo)簽,例如:

...

每個(gè)標(biāo)簽都可以指定一個(gè)URI結(jié)構(gòu)以及data的MIME類型。一個(gè)完整的URI由scheme、host、port和path組成,其結(jié)構(gòu)如下所示:

://:/

其中scheme既可以是Android中常見的協(xié)議,也可以是我們自定義的協(xié)議。Android中常見的協(xié)議包括content協(xié)議、http協(xié)議、file協(xié)議等,自定義協(xié)議可以使用自定義的字符串。

如下是一個(gè)content協(xié)議的URI:

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

在該URI中,scheme是content,host是com.example.project,port是200,path是folder/subfolder/etc。

如下是一個(gè)自定義協(xié)議的URI:

ispring://blog.csdn.NET/sunqunsunqun

在該URI中,scheme是ispring,host是blog.csdn.Net,沒有明確設(shè)定port,path是sunqunsunqun。

組成URI的這些屬性在標(biāo)簽中都是可選的 ,但存在如下的依賴關(guān)系:

如果沒有指定scheme,那么host參數(shù)會(huì)被忽略

如果沒有指定host,那么port參數(shù)會(huì)被忽略

如果scheme和host都沒有指定,path參數(shù)會(huì)被忽略

當(dāng)我們將intent對(duì)象中的Uri參數(shù)與intent-filter中的標(biāo)簽指定的URI格式進(jìn)行對(duì)別時(shí),我們我們只對(duì)比intent-filter的標(biāo)簽指定的部分,例如:

如果intent-filter中只指定了scheme,那么所有帶有該sheme的URI都能匹配到該intent-filter。

如果intent-filter中只指定了scheme和authority(authority包括host和port兩部分)而沒有指定path,那么所有具有相同scheme和authority的URI都能匹配到該intent-filter,而不用考慮path為何值。

如果intent-filter中同時(shí)指定了scheme、authority和path,那么只有具有相同scheme、authority和path的URI才能匹配到該intent-filter。

需要注意的是,intent-filter的標(biāo)簽在指定path的值時(shí),可以在里面使用通配符*,起到部分匹配的效果。

data測(cè)試需要同時(shí)將intent對(duì)象中的URI、MIME類型與intent-filter的標(biāo)簽中指定的URI、MIME類型進(jìn)行對(duì)比。

我們知道一個(gè)intent-filter下可以有多個(gè)標(biāo)簽,intent對(duì)象無需通過所有的標(biāo)簽測(cè)試,一般情況下,我們的intent對(duì)象只需通過了其中一個(gè)標(biāo)簽的測(cè)試并滿足某些特定情形下的一些條件,那么該intent對(duì)象就通過了該intent-filter的data測(cè)試。

進(jìn)行對(duì)比的規(guī)則分以下幾種情況:

intent對(duì)象不包含URI和MIME類型

這種情況下,只有當(dāng)intent-filter也沒有指定任何URI和MIME類型的時(shí)候才能通過data測(cè)試。

例如我們有如下intent對(duì)象:

Intent intent = new Intent();

intent.setAction("com.ispring.action.ACTION_TEST1");

上面的intent對(duì)象可以通過下面的intent-filter的data測(cè)試:

上面的intent對(duì)象無法通過下面的intent-filter測(cè)試:

intent對(duì)象包含URI但不包含MIME類型

這種情況下,只有當(dāng)intent對(duì)象的URI匹配到了intent-filter中的URI格式,并且intent-filter沒有指定MIME類型的時(shí)候才能通過data測(cè)試。需要注意的是,這里所說的intent-filter沒有指定MIME類型的情形指的是intent-filter中所有的標(biāo)簽都沒有指定MIME類型,即整個(gè)intent-filter中完全沒有android:mimeType這幾個(gè)字,理解這點(diǎn)很重要,大家在下面的幾個(gè)示例中可以體會(huì)到這點(diǎn)。

例如有如下intent對(duì)象:

Intent intent = new Intent();

intent.setAction("com.ispring.action.ACTION_TEST1");

Uri uri = Uri.parse("ispring://blog.csdn.net/sunqunsunqun");

intent.setData(uri);

上面的intent能通過如下的intent-filter的data測(cè)試:

上面的intent對(duì)象可以通過以下intent-filter的data測(cè)試:

intent對(duì)象雖然不能通過scheme為sunqun的標(biāo)簽測(cè)試,但是可以通過scheme為ispring的data標(biāo)簽測(cè)試,且intent對(duì)象和intent-filter中的兩個(gè)標(biāo)簽都沒有指定MIME,所以上面的intent對(duì)象可以通過該intent-filter測(cè)試。

上面的intent對(duì)象無法通過以下intent-filter的標(biāo)簽測(cè)試:

上面的intent對(duì)象之所以不能通過intent-filter中唯一的一個(gè)標(biāo)簽測(cè)試是因?yàn)槲覀兊膇ntent對(duì)象沒有指定MIME類型,但是上面的標(biāo)簽通過android:mimeType="text/plain"設(shè)置了MIME類型。

上面的intent對(duì)象無法通過以下intent-filter的data測(cè)試:

上面的intent對(duì)象之所以無法通過該intent-filter中的data測(cè)試,是因?yàn)閕ntent對(duì)象沒有設(shè)置MIME類型,但是intent-filter中第二個(gè)data標(biāo)簽通過android:mimeType="text/plain"設(shè)置了MIME類型。

intent對(duì)象包含MIME類型但不包含URI

這種情況下,只有當(dāng)intent中的MIME類型與intent-filter中列出的MIME類型相同,并且intent-filter沒有指定任何的URI格式的時(shí)候才能通過data測(cè)試。需要注意的是,這里所說的intent-filter沒有指定任何的URI格式的情形指的是intent-filter中所有標(biāo)簽都沒有指定URI,即整個(gè)intent-filter中完全沒有android:scheme、android:host、android:port以及android:path,理解這點(diǎn)很重要,大家在下面的幾個(gè)示例中可以體會(huì)到這點(diǎn)。

例如有如下intent對(duì)象:

Intent intent = new Intent();

intent.setAction("com.ispring.action.ACTION_TEST1");

intent.setType("text/plain");

上面的intent對(duì)象可以通過以下intent-filter的data測(cè)試:

上面的intent對(duì)象可以通過下面的intent-filter的data測(cè)試:

上面的intent對(duì)象雖然沒有通過MIME類型為image/*的第一個(gè)data標(biāo)簽測(cè)試,但能通過第二個(gè)data標(biāo)簽測(cè)試,并且intent對(duì)象和intent-filter都沒有指定任何的URI格式。

上面的intent對(duì)象不能通過以下intent-filter中的data測(cè)試:

上面的intent對(duì)象中沒有設(shè)置URI信息,但是在該intent-filter中設(shè)置了URI中的scheme值,所以intent無法通過intent-filter的data測(cè)試。

上面的intent對(duì)象無法通過以下intent-filter中的data測(cè)試:

上面的intent對(duì)象沒有指定URI信息,但是上面的intent-filter中第二個(gè)標(biāo)簽設(shè)置了URI中的scheme信息,所以intent對(duì)象無法通過該intent-filter的data測(cè)試。

intent對(duì)象同時(shí)包含URI和MIME類型

這種情況下,要分別測(cè)試URI以及MIME類型測(cè)試是否通過,只有URI以及MIME測(cè)試都通過了,data測(cè)試才能通過。

對(duì)于MIME測(cè)試:如果intent的MIME類型能夠匹配intent-filter中列出的某一個(gè)標(biāo)簽中的MIME類型值,那么MIME類型測(cè)試就通過了。

對(duì)于URI測(cè)試:

又細(xì)分兩種情況,滿足下面的任何一種情況都可以通過URI測(cè)試。

如果intent的URI格式能夠匹配intent-filter中列出的某一個(gè)中的URI,那么URI測(cè)試就通過了。

如果intent的URI是content:協(xié)議或file:協(xié)議,并且整個(gè)intent-filter的所有標(biāo)簽中都沒有指定URI,那么該intent也能通過URI測(cè)試。換句話說,如果一個(gè)intent-filter只列出了MIME類型,沒有列出任何URI相關(guān)的格式的話,那么這個(gè)intent-filter就默認(rèn)是支持content:協(xié)議或file:協(xié)議的。

下面舉幾個(gè)例子大家自己體會(huì)一下。

假設(shè)有如下協(xié)議為自定義協(xié)議ispring:的intent對(duì)象:

Intent intent = new Intent();

intent.setAction("com.ispring.action.ACTION_TEST1");

Uri uri = Uri.parse("ispring://blog.csdn.net/sunqunsunqun");

String type = "text/plain";

intent.setDataAndType(uri, type);

上面的intent對(duì)象可以通過下面的intent-filter的data測(cè)試:

上面的intent對(duì)象無法通過下面的intent-filter的data測(cè)試:

port不滿足,URI測(cè)試不通過,導(dǎo)致data測(cè)試失敗。

上面的intent對(duì)象無法通過下面的intent-filter的data測(cè)試:

android:mimeType不滿足,MIME類型測(cè)試不通過,導(dǎo)致data測(cè)試失敗。

假設(shè)有如下協(xié)議為content:的intent對(duì)象:

Intent intent = new Intent();

intent.setAction("com.ispring.action.ACTION_TEST1");

Uri uri = Uri.parse("content://com.ispring.test");

String type = "text/plain";

intent.setDataAndType(uri, type);

上面的intent對(duì)象無法通過下面的intent-filter的data測(cè)試:

URI中的scheme不匹配,導(dǎo)致URI測(cè)試不通過,導(dǎo)致data測(cè)試失敗。

上面的intent對(duì)象可以通過下面的intent-filter的data測(cè)試:

intent中使用的是content:協(xié)議,并且整個(gè)intent-filter中都沒有定義URI格式,所以URI測(cè)試是可以通過的,并且MIME類型能找到匹配項(xiàng),所以可以通過data測(cè)試。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉