Intent是什麼呢?來看Android官網上的定義:
An intent is an abstractdescription of an operation to be performed. It can be used with startActivity tolaunch an Activity, broadcastIntent tosend it to any interestedBroadcastReceiver components,and startService(Intent) or bindService(Intent,ServiceConnection, int) tocommunicate with a background Service.
An Intent provides afacility for performing late runtime binding between the code in differentapplications. Its most significant use is in the launching of activities, whereit can be thought of as the glue between activities. It is basically a passivedata structure holding an abstract description of an action to be performed.
一、Intent的屬性構成
Android會根據Intent來啟動相應的組件,至於啟動哪個組件,則取決於Intent中包含的屬性。理論上,Intent可以包含如下屬性:Component name、Action、Data、Category、Extra、Flags。下面我們來分別看這些屬性的用法:
1、Component name
Component name屬性指明用來處理這個Intent的組件的名稱,它是一個ComponentName類對象。Componentname是一個Intent的可選屬性。如果設定了這個屬性,那麼該Intent將會被發送給Component name指定的組件,這個Intent被稱為“顯式Intent”。如果沒有設定Component name屬性,則Android會使用Intent的其它屬性決定合適的發送目標組件,這個Intent被稱為“隱式Intent”。
Component name屬性可以通過Intent類的setComponent()、setClass()或者setClassName()三個成員函數設定,可以通過getComponent()成員函數讀取。例如:
//建立一個ComponentName對象 ComponentNamecomponentName = new ComponentName( FirstActivity.this,SecondActivity.class); Intentintent = new Intent(); //設定Intent的Component屬性 intent.setComponent(componentName); //啟動SecondActivity startActivity(intent); //建立一個ComponentName對象 ComponentNamecomponentName = new ComponentName( FirstActivity.this,SecondActivity.class); Intentintent = new Intent(); //設定Intent的Component屬性 intent.setComponent(componentName); //啟動SecondActivity startActivity(intent);
上面的代碼可以簡化為:
Intent intent = new Intent(FirstActivity.this,SecondActivity.class); //啟動SecondActivity startActivity(intent); Intent intent = new Intent(FirstActivity.this,SecondActivity.class); //啟動SecondActivity startActivity(intent);
2、Action
Action屬性工作表示Intent所觸發的目標組件將要執行的動作。在Broadcast Intent中,Action用來表示已經發生即將報告給目標組件的動作。在Intent類中,已經定義好許多Action常量,開發人員也可以自訂Action,自訂Action的名稱必須是獨一無二的字串,所以,一個好的習慣是使用基於Java包的命名方式。
Action可以通過Intent類的setAction()成員函數進行設定,通過getAction()成員函數進行讀取。看下面的例子:
//聲明一個Intent對象 Intentintent = new Intent(); //設定Action屬性,ACTION_DIAL表示跳到撥號介面 intent.setAction(Intent.ACTION_DIAL); startActivity(intent); //聲明一個Intent對象Intentintent = new Intent();//設定Action屬性,ACTION_DIAL表示跳到撥號介面intent.setAction(Intent.ACTION_DIAL);startActivity(intent);
3、Data
Data屬性是對Action指定的動作要操作的資料的封裝,包括動作要操作的資料的URI以及MIME類型。不同類型的Action會有不同的Data封裝,例如:如果Action是ACTION_EDIT,則Data應該是包含用來編輯文檔的URI。如果Action是ACTION_CALL,則Data應該是包含號碼的tel:URI。如果Action是ACTION_VIEW,則Data應該是http:URI。
顯示圖片的組件不應該拿來播放音頻,所以除了資料的URI外,資料的類型也很重要。在很多情況下,資料類型可以從URI中推斷,尤其是content:URI,它表示資料存在於裝置上並由ContentProvider控制,但是,如果有必要,Data中除了資料的URI外,還可以顯式的包含其MIME類型。
我們可以通過Intent類的setData()成員函數設定資料的URI,通過setType()成員函數設定資料的MIME類型,也可以通過setDataAndType()成員函數同時設定資料URI和MIME類型。可以通過getData()成員函數取得資料URI,通過getType()成員函數讀取MIME類型。
4、Category
Category屬性描述了用來處理這個Intent的目標組件所屬的類別。一個Intent最多隻能包含一個Action屬性,但是可以具有多個Category屬性。與Action類似,Intent類也預定義了一些Category常量。
我們可以通過Intent類的addCategory()成員函數添加一個Category屬性,通過removeCategory()成員函數刪除一個Category屬性,通過getCategory()成員函數獲得當前對象中包含的全部Category屬性。
5、Extras
Extras屬性封裝了一些額外的附加資訊,這些資訊是以索引值對的形式存在。
就象一些Action與特定類型的Data URI匹配一樣,有些Action與特定的Extras匹配。例如,Action為ACTION_HEADSET_PLUG,則Extras用state來表示耳機是否被插入,用name表示耳機的類型。再比如,如果Action為ACTION_TIMEZONE_CHANGED,則Extras用time-zone來表示新時區。
Intent類定義了多個putXXX()方法,如putExtra(),用來設定不同類型的Extra資料。也定義了多個getXXX()方法,如getDoubleExtra(),用來讀取Extra資料。這些方法和Bundle類有些類似,實際上,Extra可以通過putExtras()和getExtras()方法進行Bundle的設定和讀取。
6、Flags
Flags屬性多數用來指示Android系統如何啟動Activity(如Activity屬於哪個Task)以及啟動後如何對待(如它是否屬於近期的Activity列表)。所有的Flags都定義在Intent類中。
二、Intent過濾器(Intent Filter)
能夠接收處理Intent的組件(如Activity、Service、BroadcastReceiver)必須告訴Android系統它能夠響應處理什麼樣的Intent,這可以通過在AndroidManifest.xml檔案中聲明Intent過濾器(Intent Filter)實現。
IntentFilter描述該組件所能響應Intent的能力,即組件所能接收的Intent應該具有什麼樣的Action,Data或Category屬性。比如,一個網頁瀏覽器程式的IntentFilter應該聲明它所希望接收的Intent應該具有ACTION_WEB_SEARCH,以及與之相關的Data應該是網頁地址URI格式。
1、 Action測試
(1) Intent Filter應該至少包含一個Action測試,否則將屏蔽掉所有的Intent。
(2) 如果Intent沒有定義Action屬性,則只要Intent Filter包含一個Action測試,則這個Intent就會通過測試。
(3) 一個Intent只能有一個Action屬性,但是一個Intent Filter可以定義多個Action測試,如果Intent的Action屬性與某一條Intent Filter的Action測試匹配,就通過測試。
2、 Category測試
(1) 一個Intent可以定義多個Category屬性,Intent Filter也可以包含多個Category測試,只有當Intent的所有Category屬性在Intent Filter的Category測試中均有匹配項時,Category測試才算通過。
(2) Intent Filter中多餘的Category測試項不會導致測試失敗。
(3) 原則上講,無論Intent Filter如何定義,沒有定義Category的Intent總是可以通過Category測試。然而,需要注意,Android預設為所有通過startActivity()方法傳遞的隱式Intent設定一個Category屬性,即android.intent.category.DEFAULT(CATEGORY_DEFAULT),所以,接收隱式Intent的Activity必須在過濾器中聲明android.intent.category.DEFAULT(包含android.intent.action.MAIN和android.intent.category.LAUNCHER設定的是一個例外。它們表明Activity作為新任務啟動並且顯示在啟動螢幕上,包含android.intent.category.DEFAULT與否均可)。
(4) 一個沒有指定任何Category測試的Intent Flilter只會匹配沒有定義Category屬性的Intent。
3、 Data測試
Intent Filter的Data測試可以指定URI和資料類型(MIME類型),URI可以分為scheme、host、port和path幾個獨立的部分:scheme://host:port/path
例如:content://com.liuhaoyu.project:1000/folder/subfolder/config
其中,scheme是content,host是com.liuhaoyu.project,port是1000,path是folder/subfolder/config。
host和port一起組成了URI授權,如果host沒有指定,則忽略port。
這些屬性都是可選的,但是相互之間並非完全獨立。如果授權有效,則scheme必須指定。如果path有效,則scheme和授權必須指定。
當Intent的Data屬性與Intent Filter的Data測試相比較時,僅僅與Intent Filter中實際提到的URI部分相比較。例如,如果Intent Filter僅指定了scheme,則所有具有該scheme的URI都能匹配該Intent Filter。