什么是Intent
Intent是一種運(yùn)行時(shí)綁定(run-time binding)機(jī)制,它能在程序運(yùn)行過程中連接兩個(gè)不同的組件。通過Intent,你的程序可以向Android表達(dá)某種請求或者意愿,Android會(huì)根據(jù)意愿的內(nèi)容選擇適當(dāng)?shù)慕M件來完成請求。比如,有一個(gè)Activity希望打開網(wǎng)頁瀏覽器查看某一網(wǎng)頁的內(nèi)容,那么這個(gè)Activity只需要發(fā)出WEB_SEARCH_ACTION給Android,Android就會(huì)根據(jù)Intent的請求內(nèi)容,查詢各組件注冊時(shí)聲明的IntentFilter,找到網(wǎng)頁瀏覽器的Activity來瀏覽網(wǎng)頁。
Android的三個(gè)基本組件——Activity,Service和Broadcast Receiver——都是通過Intent機(jī)制激活的,不同類型的組件有不同的傳遞Intent方式:
1.1 要激活一個(gè)新的Activity,或者讓一個(gè)現(xiàn)有的Activity做新的操作,可以通過調(diào)用Context.startActivity()或者Activity.startActivityForResult()方法。
1.2 要啟動(dòng)一個(gè)新的Service,或者向一個(gè)已有的Service傳遞新的指令,調(diào)用Context.startService()方法或者調(diào)用Context.bindService()方法將調(diào)用此方法的上下文對象與Service綁定。
1.3 Context.sendBroadcast()、Context.sendOrderBroadcast()、Context.sendStickBroadcast()這三個(gè)方法可以發(fā)送Broadcast Intent。發(fā)送之后,所有已注冊的并且擁有與之相匹配IntentFilter的BroadcastReceiver就會(huì)被激活。
Intent一旦發(fā)出,Android都會(huì)準(zhǔn)確找到相匹配的一個(gè)或多個(gè)Activity,Service或者BroadcastReceiver作響應(yīng)。所以,不同類型的Intent消息不會(huì)出現(xiàn)重疊,即Broadcast的Intent消息只會(huì)發(fā)送給BroadcastReceiver,而決不會(huì)發(fā)送給Activity或者Service。由startActivity()傳遞的消息也只會(huì)發(fā)給Activity,由startService()傳遞的Intent只會(huì)發(fā)送給Service。
Intent的構(gòu)成
要在不同的activity之間傳遞數(shù)據(jù),就要在intent中包含相應(yīng)的內(nèi)容,一般來說數(shù)據(jù)中最基本的應(yīng)該包括:
Action:用來指明要實(shí)施的動(dòng)作是什么,比如說ACTION_VIEW, ACTION_EDIT等。具體的可以查閱android SDK-> reference中的Android.content.intent類,里面的constants中定義了所有的action。
一些常用的Action:
ACTION_CALL activity 啟動(dòng)一個(gè)電話.
ACTION_EDIT activity 顯示用戶編輯的數(shù)據(jù).
ACTION_MAIN activity 作為Task中第一個(gè)Activity啟動(dòng)
ACTION_SYNC activity 同步手機(jī)與數(shù)據(jù)服務(wù)器上的數(shù)據(jù).
ACTION_BATTERY_LOW broadcast receiver 電池電量過低警告.
ACTION_HEADSET_PLUG broadcast receiver 插拔耳機(jī)警告
ACTION_SCREEN_ON broadcast receiver 屏幕變亮警告.
ACTION_TIMEZONE_CHANGED broadcast receiver 改變時(shí)區(qū)警告.
Data: 要事實(shí)的具體的數(shù)據(jù),一般由一個(gè)Uri變量來表示
Category:一個(gè)字符串,包含了關(guān)于處理該intent的組件的種類的信息。一個(gè)intent對象可以有任意個(gè)category。intent類定義了許多category常數(shù).
addCategory()方法為一個(gè)intent對象增加一個(gè)category,
removeCategory刪除一個(gè)category,
getCategories()獲取intent所有的category.
Type:顯式指定Intent的數(shù)據(jù)類型(MIME)(多用途互聯(lián)網(wǎng)郵件擴(kuò)展,Multipurpose Internet Mail Extensions)。比如,一個(gè)組件是可以顯示圖片數(shù)據(jù)的而不能播放聲音文件。很多情況下,data類型可在URI中找到,比如content:開頭的URI,表明數(shù)據(jù)由設(shè)備上的content provider提供。但是通過設(shè)置這個(gè)屬性,可以強(qiáng)制采用顯式指定的類型而不再進(jìn)行推導(dǎo)。
MIME類型有2種形式:
1.1 單個(gè)記錄的格式: vnd.android.cursor.item/vnd.yourcompanyname.contenttype,如:content://com.example.transportationprovider/trains/122(一條列車信息的uri)的MIME類型是vnd.android.cursor.item/vnd.example.rail
1.2 多個(gè)記錄的格式:vnd.android.cursor.dir/vnd.yourcompanyname.contenttype,如:content://com.example.transportationprovider/trains (所有列車信息)的MIME類型是vnd.android.cursor.dir/vnd.example.rail
component:指定Intent的目標(biāo)組件的類名稱。通常 Android會(huì)根據(jù)Intent 中包含的其它屬性的信息,比如action、data/type、category進(jìn)行查找,最終找到一個(gè)與之匹配的目標(biāo)組件。但是,如果 component這個(gè)屬性有指定的話,將直接使用它指定的組件,而不再執(zhí)行上述查找過程。指定了這個(gè)屬性以后,Intent的其它所有屬性都是可選的。例如:
Intent it = new Intent(Activity.Main.this, Activity2.class); startActivity(it);
startActivity(it);
extras:附加信息,例如ACTION_TIMEZONE_CHANGED的intent有一個(gè)"time-zone"附加信息來指明新的時(shí)區(qū),而ACTION_HEADSET_PLUG有一個(gè)“state”附加信息來指示耳機(jī)是被插入還是被拔出。intent對象有一系列put...()和set...()方法來設(shè)定和獲取附加信息。 這些方法和Bundle對象很像。事實(shí)上附加信息可以使用putExtras()和getExtras()作為Bundle來讀和寫。例如:
//用Bundle傳遞數(shù)據(jù) Intent it = new Intent(Activity.Main.this, Activity2.class); Bundle bundle=new Bundle(); bundle.putString("name", "This is from MainActivity!"); it.putExtras(bundle); startActivity(it); //獲得數(shù)據(jù) Bundle bundle=getIntent().getExtras(); String name=bundle.getString("name");
intent的解析:
在應(yīng)用中,我們可以以兩種形式來使用Intent:
1.1 顯式Intent:指定了component屬性的Intent(調(diào)用setComponent(ComponentName)或者setClass(Context, Class)來指定)。通過指定具體的組件類,通知應(yīng)用啟動(dòng)對應(yīng)的組件。
2.2 隱式Intent:沒有指定comonent屬性的Intent。這些Intent需要包含足夠的信息,這樣系統(tǒng)才能根據(jù)這些信息,在在所有的可用組件中,確定滿足此Intent的組件。
對于直接Intent,Android不需要去做解析,因?yàn)槟繕?biāo)組件已經(jīng)很明確,Android需要解析的是那些間接Intent,通過解析將 Intent映射給可以處理此Intent的Activity、Service或Broadcast Receiver。
Intent解析機(jī)制
Intent解析機(jī)制主要是通過查找已注冊在AndroidManifest.xml中的所有<intent-filter>及其中定義的Intent,通過PackageManager(注:PackageManager能夠得到當(dāng)前設(shè)備上所安裝的
application package的信息)來查找能處理這個(gè)Intent的component。在這個(gè)解析過程中,Android是通過Intent的action、type、category這三個(gè)屬性來進(jìn)行判斷的,判斷方法如下:
1.1 如果Intent指明定了action,則目標(biāo)組件的IntentFilter的action列表中就必須包含有這個(gè)action,否則不能匹配;
1.2 如果Intent沒有提供type,系統(tǒng)將從data中得到數(shù)據(jù)類型。和action一樣,目標(biāo)組件的數(shù)據(jù)類型列表中必須包含Intent的數(shù)據(jù)類型,否則不能匹配。
1.3 如果Intent中的數(shù)據(jù)不是content:類型的URI,而且Intent也沒有明確指定type,將根據(jù)Intent中數(shù)據(jù)的scheme(比如 http:或者mailto:)進(jìn)行匹配。同上,Intent 的scheme必須出現(xiàn)在目標(biāo)組件的scheme列表中。
1.4 如果Intent指定了一個(gè)或多個(gè)category,這些類別必須全部出現(xiàn)在組建的類別列表中。比如Intent中包含了兩個(gè)類別:LAUNCHER_CATEGORY和ALTERNATIVE_CATEGORY,解析得到的目標(biāo)組件必須至少包含這兩個(gè)類別。