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