intent 总结
Activity、Service和Broadcast Receiver這些核心組件之間通過(guò)消息激活,這個(gè)消息就是Intent。
Intent消息可用于當(dāng)前運(yùn)行時(shí)同應(yīng)用內(nèi)部的組件之間或者不同應(yīng)用的組件之間通信。Intent自身,即一個(gè)Intent對(duì)象,包含說(shuō)明一個(gè)執(zhí)行操作的抽象數(shù)據(jù)結(jié)構(gòu),傳遞給執(zhí)行操作的組件,或者,常見(jiàn)于broadcast的情況,該數(shù)據(jù)結(jié)構(gòu)用于描述正在執(zhí)行或者已經(jīng)發(fā)生的事情。
針對(duì)組件類型不同,發(fā)送Intent有不同的機(jī)制:
- 針對(duì)Activity,Context.startActivity()方法傳遞Intent,啟動(dòng)一個(gè)新的Activity,或者Activity.startActivityForResult()方法啟動(dòng)新的Activity做完事情后返回到本Activity來(lái);
- 針對(duì)Service,Context.startService()方法,用于創(chuàng)建一個(gè)Service或者傳遞給已經(jīng)運(yùn)行Service一個(gè)指令,于此類似,Context.bindService()建立當(dāng)前組件和Service之間的連接,可選的,如果該Service未運(yùn)行,可以創(chuàng)建新的實(shí)例;
- 針對(duì)Broadcast Receiver,可通過(guò):Context.sendBroadcast()、Context.sendOrderedBroadcast()或者Context.sendStickyBroadcast()方法發(fā)送Intent給所有感興趣的broadcast receiver。
?
在以上各種情況下,Android系統(tǒng)找到適合響應(yīng)該Intent的activity、service或者broadcast service集合。不會(huì)出現(xiàn)重疊現(xiàn)象,即,broadcast intent只會(huì)發(fā)送給broadcast receiver,而不會(huì)發(fā)送給Activity或者Service。
Intent對(duì)象
Intent對(duì)象可綁定一組信息:
- 接收intent的組件需要的信息,比如需要調(diào)用系統(tǒng)照相機(jī)Activity,要告知它照片存放的路徑;
- Android系統(tǒng)需要的信息,比如那個(gè)種類的組件可以處理這個(gè)Intent,在比如,告知如何啟動(dòng)Activity(比如要求它在哪個(gè)task中)。
Intent對(duì)象主要包含以下內(nèi)容:
- componnet name,組件名稱,可處理這個(gè)Intent的組件名稱。組件名稱是可選的,如果填寫,Intent對(duì)象會(huì)發(fā)送給指定組件名稱的組件,否則,也可以通過(guò)其他Intent信息定位到適合的組件。組件名稱是個(gè)ComponentName類型的對(duì)象,該對(duì)象又包括:
- 目標(biāo)組件完整的類名,比如:com.example.project.app.FreneticActivity;
- 在manifest文件中設(shè)置的包名,組件的包名和manifest中定義的包名可以不匹配。
- action,命名動(dòng)作的字符串,用于執(zhí)行動(dòng)作,或者,在廣播的情況下,表示發(fā)生的或者要報(bào)告的動(dòng)作。Intent類定義了一組action常量,見(jiàn)API的Intent.ACTION_*。這些是Intent類預(yù)制的一些通用action,還有一些action定義在android其他API中。用戶可以定義自己的action字符串常量,用于激活自己的應(yīng)用組件。這需要把應(yīng)用的包名作為該字串的前綴,比如:com.example.project.SHOW_COLOR。action名稱很像java調(diào)用的方法名,下面提到的data和extra類似參數(shù)和返回值。
- data,起到表示數(shù)據(jù)和數(shù)據(jù)MIME類型的作用。不同的action是和不同的data類型配套的。比如,action是ACTION_EDIT,那么data要包含要編輯的文檔URI。如果action是ACTION_CALL,data可能是tel:前綴后面跟電話號(hào)碼,在比如action是ACTION_VIEW,data是http:開(kāi)頭的URI,則應(yīng)該是顯示或者下載該uri的內(nèi)容。在匹配intent到能處理該組件的過(guò)程中,data(MIME類型)類型是很重要的。比如,一個(gè)組件是可以顯示圖片數(shù)據(jù)的而不能播放聲音文件。很多情況下,data類型可在URI中找到,比如content:開(kāi)頭的URI,表明數(shù)據(jù)在設(shè)備上,而且有content provider控制。但是有些類型只能顯式的設(shè)置。setData()方法只能設(shè)置data的uri,setType()可設(shè)置MIME類型,setDataAndType()即可設(shè)置URI也可設(shè)置MIME類型。
- category,包含處理intent組件種類的額外信息。對(duì)一個(gè)Intent可以設(shè)置任意多個(gè)category描述,和cation類似,Intent類預(yù)制了一些category常量,Intent.CATEGORY_*。
- extras,可以看作一個(gè)Map,通過(guò)鍵值對(duì),可為處理Intent組件提供一些附加的信息。可通過(guò)put..()和get..()存取信息。也可以獲取Bundle對(duì)象,然后通過(guò)putExtras()和getExtras()方法存取。
- flug,用于多種情況,在intent增加flug,比如可以指示Android如何啟動(dòng)一個(gè)activity,比如是否屬于或者不屬于當(dāng)前task,以及,處理完畢后activity的歸屬。這些flag都定義在Intent類的常量中。
Intent解析
intent的投遞,有兩種方式:
- 顯式的設(shè)定目標(biāo)組件的component名稱。不過(guò)有時(shí)開(kāi)發(fā)者不知道其他應(yīng)用的component名稱。顯式方式常用于自己應(yīng)用內(nèi)部的消息傳遞,比如應(yīng)用中一個(gè)activity啟動(dòng)一個(gè)相關(guān)的service或者啟動(dòng)一個(gè)姊妹activity;
- 隱式intent,component名稱為空的情況。這種方式往往用于激活其他應(yīng)用中的組件。
android投遞一個(gè)顯式的intent,只需找到對(duì)應(yīng)名稱的組件即可。
隱式的intent需要用到不同的策略。android需要找到處理這個(gè)intent的最合適組件(集合)。要通過(guò)intent filter,比較intent對(duì)象和組件關(guān)聯(lián)結(jié)構(gòu)。filter根據(jù)組件的能力決定他們能處理哪些intent。android系統(tǒng)打開(kāi)合適的組件處理相應(yīng)的隱式intent。如果組件不包含任何intent filter,那只能接收顯式的intent。帶filter的組件既可接收隱式intent也可接收顯式的。
Intent有三個(gè)方面可用于intent filter:
- action
- data,包括URI部分和數(shù)據(jù)類型部分
- category
extra和flag在這方面不起作用。
Intent filter
為了能支持隱式intent,activity、service和broadcast receiver會(huì)包含1到多個(gè)intent filter。每個(gè)intent filter描述組件的可接收一組intent的能力。在intent filter中,說(shuō)明了可接受的類型,以及不想要的intent。隱式的intent要想投遞到一個(gè)組件,只需通過(guò)組件的一個(gè)filter即可。
組件把filter分成多個(gè),是為了針對(duì)具體不同的任務(wù)。在sample中的Note pad示例中,NoteEditor activity有兩個(gè)filter,一個(gè)用于啟動(dòng)并打開(kāi)指定的note,另一個(gè)是為了打開(kāi)新的空的note。
一個(gè)intent filter是一個(gè)IntentFilter類的實(shí)例。但是,android系統(tǒng)必須在組件未啟動(dòng)的情況下就知道它的能力,因此intent filter一般不會(huì)在java代碼中設(shè)置,而是在應(yīng)用的manifest文件中作為<intent-filter>元素的方式聲明。一個(gè)例外是,為broadcast receiver注冊(cè)動(dòng)態(tài)的filter,可以調(diào)用Context.registerReceiver()方法,通過(guò)直接實(shí)例化IntentFilter對(duì)象創(chuàng)建。
filter有三個(gè)平等的部分:action、data和category。隱式intent將測(cè)試這三個(gè)部分。一個(gè)intent要想投遞到一個(gè)組件,那么這三個(gè)測(cè)試都要通過(guò)才行。當(dāng)然如果組件有多個(gè)intent filter,可能一個(gè)intent沒(méi)有通過(guò),但是通過(guò)了另外的一個(gè),這樣也可以把intent投遞到組件。
action測(cè)試
在intent filter中可以包含多個(gè)action,比如:
<intent-filter . . . >?
??? <action android:name="com.example.project.SHOW_CURRENT" />?
??? <action android:name="com.example.project.SHOW_RECENT" />?
??? <action android:name="com.example.project.SHOW_PENDING" />?
??? . . .?
</intent-filter>
要想通過(guò)測(cè)試,intent中的action名稱要匹配其中之一。
如果intent filter中不包含action列表,而intent指定action,那么intent沒(méi)有匹配的action,不通過(guò);intent未指定action,而intent filter指定,會(huì)自動(dòng)通過(guò)測(cè)試。
category測(cè)試
在intent filter中可包含category列表:
<intent-filter . . . >?
??? <category android:name="android.intent.category.DEFAULT" />?
??? <category android:name="android.intent.category.BROWSABLE" />?
??? . . .?
</intent-filter>
intent想通過(guò)測(cè)試,必須匹配一個(gè)intent filter中的category。
原理上講,intent如果沒(méi)有category設(shè)置,那么總是可以通過(guò)測(cè)試。這基本上是正確的,但是有一個(gè)例外。Android在為所有隱式intent執(zhí)行startActivity()方法的時(shí)候,會(huì)認(rèn)為它們至少包含了一個(gè)android.intent.category.DEFAULT。因此,如果activity想收到隱式intent,必須加入這個(gè)category。
date測(cè)試
data元素在intent filter元素中,可以重復(fù)多次(action和category不允許重復(fù)的),也可以根本沒(méi)有。比如:
<intent-filter . . . >?
??? <data android:mimeType="video/mpeg" android:scheme="http" . . . />?
??? <data android:mimeType="audio/mpeg" android:scheme="http" . . . />?
??? . . .?
</intent-filter>
?
在data元素中指定uri和數(shù)據(jù)類型(MIME類型)。uri是被分開(kāi)表示的:
scheme://host:port/path
其中host和port是關(guān)聯(lián)的,如果host沒(méi)有設(shè)置,port也會(huì)忽略。
所有這些屬性都是可選的,但是不是獨(dú)立的。比如,如果要設(shè)置path,那么也必須設(shè)置schema、host和port。
在比較intent中的uri和intent filter中指定的uri時(shí),只會(huì)比較intent filter中提及的URL部分。比如,intent filter中只提及了schema,那么所有url包含這個(gè)schema的都匹配。在filter的path部分可以使用通配符做到靈活的匹配。
mimeType屬性,比uri方式更常用。intent和intent filter都可以使用mime通配符的方式,比如,text/*。
如果既有mimeType,又有uri的情況,比較規(guī)則如下:
- 如果intent和intent filter都沒(méi)有設(shè)置任何uri和mimetype,通過(guò);
- intent包含uri但是沒(méi)有data type的情況,intent filter的uri部分與之匹配,而且也沒(méi)有data type部分,可以通過(guò),比如mailto:和tel:
- intent對(duì)象包含數(shù)據(jù)類型但是沒(méi)有uri部分,那么僅當(dāng)intent filter也只有數(shù)據(jù)類型,而沒(méi)有uri部分的時(shí)候能通過(guò);
- intent對(duì)象包括uri和數(shù)據(jù)類型(或者數(shù)據(jù)類型在uri中),分兩部分測(cè)試,intent對(duì)象的數(shù)據(jù)類型要匹配intent filter,intent對(duì)象的uri,或者匹配intent filter中的uri,或者intent filter中沒(méi)有uri部分(僅當(dāng)intent對(duì)象的uri是content:或者file:的時(shí)候)。
總結(jié)
- 上一篇: 在iphone程序中打开word、exe
- 下一篇: android library proj