Intent用於啟動Activity,Service, 以及BroadcastReceiver三種組件, 同時還是組件之間通訊的重要媒介。
使用Intent啟動組件的優勢
1, Intent為組件的啟動提供了一致的編程模型。無論想要啟動的組件是Activity,Service, 還是BroadcastReceiver,都可以使用Intent封裝啟動的意圖。
2, 在某些時候, 應用程式只是想啟動具有某種特徵的組件, 並不想和某個特定的組件耦合。使用Intent可以方便的達到這種高層次解耦的目的。
Intent的Component屬性
Intent對象的setComponent(ComponentNamecomp)方法用於設定Intent的Component屬性。ComponentName包含如下幾個構造器:
ComponentName(Stringpkg, String cls)
ComponentName(Contextpkg, String cls)
ComponentName(Contextpkg, Class cls)
由以上的構造器可知, 建立一個ComponentName對象需要指定包名和類名--這就可以唯一確定一個組件類, 這樣應用程式即可根據給定的組件類去啟動特定的組件。例如:
ComponentName comp =new ComponentName(FirstActivity。this,SecondActivity。class);
Intent intent = newIntent();
intent。setComponent(comp);
以上三句代碼建立了一個intent對象, 並為其指定了Component屬性, 完全等價於下面的代碼:
Intent intent = newIntent(FirstActivity。this,SecondActivity。class);
除了使用setComponent()之外, 還可以使用setClass(),setClassName()來顯式指定目標組件, 還可以調用getComponent()方法獲得Intent中封裝的ComponentName對象。
當程式採用這種形式啟動組件時, 在Intent中明確的指定了待啟動的組件類, 此時的Intent屬於顯式intent, 顯式Intent應用場合比較狹窄, 多用於啟動本應用中的component,因為這種方式需要提前獲知目標組件類的全限定名。而隱式Intent則通過Intent中的action,category, data屬性指定目標組件需要滿足的若干條件, 系統篩選出滿足所有條件的component,從中選擇最合適的component或者由使用者選擇一個component作為目標組件啟動。
如果Intent中指定了ComponentName屬性, 則Intent的其他屬性將被忽略。
Intent的Action屬性
action屬性是一個字串, 代表某一種特定的動作。 Intent類預定義了一些action常量, 開發人員也可以自訂action。一般來說, 自訂的action應該以application的包名作為首碼, 然後附加特定的大寫字串, 例如"cn。xing。upload。action。UPLOAD_COMPLETE"就是一個命名良好的action。
Intent類的setAction()方法用於設定action,getAction()方法可以擷取Intent中封裝的action。
以下是Intent類中預定義的部分action:
ACTION_CALL--目標組件為activity,代表撥號動作;
ACTION_EDIT--目標組件為activity,代表向使用者顯示資料以供其編輯的動作;
ACTION_MAIN--目標組件為activity,表示作為task中的初始activity啟動;
ACTION_BATTERY_LOW--目標組件為broadcastReceiver,提醒手機電量過低;
ACTION_SCREEN_ON--目標組件為broadcast,表示開啟螢幕。
Intent的Category屬性
category屬性也是一個字串, 用於指定一些目標組件需要滿足的額外條件。 Intent對象中可以包含任意多個category屬性。 Intent類也預定義了一些category常量, 開發人員也可以自訂category屬性。
Intent類的addCategory()方法為Intent添加Category屬性,getCategories()方法用於擷取Intent中封裝的所有category。
以下是Intent類中預定義的部分category:
CATEGORY_HOME--表示目標activity必須是一個顯示homescreen的activity;
CATEGORY_LAUNCHER--表示目標activity可以作為task棧中的初始activity,常與ACTION_MAIN配合使用;
CATEGORY_GADGET--表示目標activity可以被作為另一個activity的一部分嵌入。
Intent的Data屬性
data屬性指定所操作資料的URI。 data經常與action配合使用, 如果action為ACTION_EDIT,data的值應該指明被編輯文檔的URI; 如果
action為ACTION_CALL,data的值應該是一個以"tel:"開頭並在其後附加號碼的URI; 如果action為ACTION_VIEW,data的值應該是一個以"http:"開頭並在其後附加網址的URI。。。
Intent類的setData()方法用於設定data屬性,setType()方法用於設定data的MIME類型,setDataAndType()方法可以同時設定兩者。可以通過getData()方法擷取data屬性的值, 通過getType()方法擷取data的MIME類型。
Intent的Extra屬性
通過Intent啟動一個component時, 經常需要攜帶一些額外的資料過去。攜帶資料需要調用Intent的putExtra()方法, 該方法存在多個重載方法, 可用於攜帶基礎資料型別 (Elementary Data Type)及其數組, String類型及其數組, Serializable類型及其數組,Parcelable類型及其數組, Bundle類型等。Serializable和Parcelable類型代表一個可序列化的對象, Bundle與Map類似,可用於儲存索引值對。
Intent的Flag屬性
flag屬性是一個int值, 用於通知android系統如何啟動目標activity,或者啟動目標activity之後應該採取怎樣的後續操作。所有的flag都在Intent類中定義, 部分常用flag如下:
FLAG_ACTIVITY_NEW_TASK--通知系統將目標activity作為一個新task的初始activity;
FLAG_ACTIVITY_NO_HISTORY--通知系統不要將目標activity放入曆史棧中;
FLAG_FROM_BACKGROUND--通知系統這個Intent來源於後台操作, 而非使用者的直接選擇。。。
IntentFilter類
IntentFilter類表示Intent過濾器, 大部分情況下, 每一個component都會定義一個或多個IntentFilter,用於表明其可處理的Intent。
一般來說,component的IntentFilter應該在AndroidManifest。xml檔案中定義。
定義的方法: 在<activity>,<receiver>, <service> 元素中增加一個或多個子項目。如:
<!-- 聲明作為程式入口的Activity-->
<activityandroid:name="。FirstActivity">
<intent-filter>
<action android:name="android。intent。action。MAIN"/>
<category android:name="android。intent。category。LAUNCHER"/>
</intent-filter>
</activity>
IntentFilter與隱式Intent
android系統處理隱式Intent時, 會比較Intent和IntentFilter的action,data, category屬性, 如果以上3個屬性全都相符的話, 則IntentFilter所屬的component就可以作為目標組件的候選(存在多個合格component時)。
1。測試action屬性。 intent最多隻能定義1個action, 而filter可以定義1個或多個action。
通過action測試的條件為: filter定義了intent的action。例如intent的action為"android。intent。action。MAIN",則定義了"android。intent。action。MAIN"這個action的filter都能通過action測試(當然, filter還可以包含更多額外的action)。
如果filter沒有定義action, 則這個filter將阻塞所有intent。如果intent沒有定義action, 那麼只要filter定義了action就可以通過action測試。
2。測試category屬性。 intent可以任意多個category,filter也可以任意個category。通過category測試的條件為: filter定義了intent的所有category。例如intent定義了"android。intent。category。DEFAULT"和"cn。xing。intent。category。UPLOAD"這2個category,則定義了以上2個category屬性的filter才能通過測試(當然, filter還可以包含更多額外的category)。
根據上面的規則, 如果一個intent沒有定義category,則所有filter都可以通過category測試。但是有一種例外: 以startActivity(intent)方式啟動一個activity時, 系統為會intent增加一個值為"android。intent。category。DEFAULT"的category,這就意味著每一個期望通過category測試的activity,都要在其filter中定義"android。intent。category。DEFAULT"(除了作為程式入口的activity)。
3。測試data屬性。 intent最多隻能定義1個data,filter則可以定義多個data。
通過data測試的條件為:
a。如果intent沒有指定data和data type,則只有沒有定義data和datetype的filter才能通過測試;
b。如果intent定義了data沒有定義datatype, 則只有定義了相同data且沒有定義datetype的filter才能通過測試;
c。如果intent沒有定義data卻定義了datatype, 則只有未定義data且定義了相同的datatype的filter才能通過測試;
d。如果intent既定義了data也定義了datatype, 則只有定義了相同的data和datatype的filter才能通過測試。
data屬性是一個URI, URI中包含scheme,host, post和path, 典型的URI為:
scheme://host:port/path
scheme, host, post和path都是可選的。比較2個data時, 只比較filter中包含的部分。比如filter的一個data只是指定了scheme部分, 則測試時只是比較data的scheme部分, 只要兩者的scheme部分相同, 就視為"相同的data"。