本節書摘來自異步社群《android 應用案例開發大全(第二版)》一書中的第6章,第6.2節intent對象,作者李甯,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視
6.2 intent對象
android開發權威指南(第二版)
上一節介紹了intent的主要作用就是封裝和傳遞各種資訊。那麼intent對象到底可以封裝和傳遞哪些資訊呢?本節将會揭開這些秘密。
6.2.1 intent對象可以封裝和傳遞哪些資訊
intent對象可以封裝和傳遞如下6種資訊。
元件名(component name)。
動作(action)。
種類(category)。
資料(data)。
附加資訊(extra)。
标志(flags)。
在6.2.1至6.2.7小節會分别介紹這6種資訊,并從6.4節開始提供大量的案例示範在android應用中如何使用這些資訊。
6.2.2 元件名(component name)
intent對象可以直接指定要通路的元件,例如,有一個名為myactivity的視窗類,可以使用下面的代碼指定該視窗類。
直接指定視窗類的class隻是其中最常用的引用方式,除此之外,還有如下3個方法可以指定具體的視窗。
setclass:指定context對象和視窗類的class。與通過intent類的構造方法傳遞資訊的作用是一樣的。
setclassname:指定context對象、字元串形式的包名和視窗類名。
setcomponent:與setclassname方法類似,隻是要傳遞的資料都封裝在了componentname對象中。
1.setclass方法
setclass方法的原型如下:
使用setcomponent方法之前先要建立componentname對象,在6.4節中會詳細介紹setcomponent方法及componentname對象的使用方法。
6.2.3 動作(action)
一般會通過視窗類的class或視窗類的全名确定某個具體的視窗,不過這些資訊都是視窗的固有屬性。然而還有第3種确定視窗的方法,這就是視窗動作(activity action)。如果用一句話解釋什麼是activity action,那就是“與視窗2綁定的一個或多個字元串”,也就是說activity action是一個字元串,而且一個視窗可以擁有多個這樣的字元串。其實activity action在前面的章節雖然未專門講解,但已經多次涉及了。每次建立android工程時都會自動建立一個主視窗,該視窗通常會在androidmanifest.xml檔案中有如下的聲明代碼。其中标簽的android:name屬性值android.intent.action.main就是一個系統提供的activity action。一旦應用程式啟動,android系統就會尋找要運作的android應用中定義了該activity action的視窗3,一旦找到,就會顯示該視窗。
盡管一個視窗可以有多個activity action,但隻能通過intent.setaction方法設定一個activity action。如果指定的activity action并不存在,當顯示視窗時(調用startactivity方法)就會抛出異常。例如,我們可以通過如下的代碼指定一個activity action,并顯示定義該activity action的視窗,如果系統中有多個視窗定義了該activity action,會顯示一個選擇清單,清單中顯示了所有定義該activity action視窗,使用者可以選擇顯示哪個視窗。
// 通過intent對象指定了一個activity action
intent intent = new intent(“mobile.android.android.myaction”);
// 如果系統中沒有定義mobile.android.android.myaction的視窗,執行下面的代碼會抛出異常
startactivity(intent);
如果使用者不想通過intent類的構造方法指定activity action,也可以通過intent.setaction方法指定action,代碼如下:
系統應用也有很多視窗定義了activity action,這些activity action可以調用android系統内置應用中的視窗。例如,照相機拍照界面、撥号界面等。雖然可以直接用字元串指定這些系統的activity action,但為了相容(android的後續版本又可以修改系統視窗的activity action),應盡量使用在intent類中定義的action常量(以action_開頭的都是action常量)。這些常量包括activity action和broadcast action,系統未定義service action。直接在代碼編輯器中輸入“intent.”就會看到所有的action常量,如圖6-1所示。
6.2.4 種類(category)
在這裡先給大家提個問題,如果系統中有多個視窗(不同應用程式中的視窗)定義了同一個action,而且自己編寫的程式中也定義了這個activity action。這樣如果通過intent.setaction方法設定這個action後顯示視窗,就會首先顯示一個選擇清單,列出了所有定義該activity action的視窗。那麼在調用自己編寫的程式中定義了該activity action的視窗時不想顯示這個選擇清單,而隻顯示自己應用中的視窗又該如何做呢?
其實解決上述問題也很簡單,就像檔案和檔案夾的關系一樣,如果想在磁盤上存儲多個同名的檔案,又不發生沖突的方法就是将這些檔案放到不同的檔案夾下。那麼action也是一樣。如果單憑action無法定位唯一的視窗,那就要再加一個可以定位的标志,這就是種類(category)。
category實際上與action一樣,也是與視窗綁定的字元串。在聲明主視窗時标簽的android:name屬性值指定的就是category。如果聲明視窗時同時指定了action和category,那麼在顯示視窗之前不僅要使用intent.setaction方法設定action,還要使用intent.addcategory方法添加category。對于intent對象來說,action與category的不同之處在于隻能為intent對象指定一個action,而category可以指定多個(從方法名setaction和addcategory就可以很容易猜到)。
category也可以和action一樣任意指定字元串。在intent類中同樣定義了一些系統的category常量,如圖6-2所示。
同時設定action和category的java代碼如下:
通過指定系統的action和category可以實作很多有趣的東西,例如,在上一章介紹的調用系統視窗就是其中之一。讀者可以在學習完這一章的内容後再回過頭來複習上一章的内容,會有更深的體會。
6.2.5 資料(data)
data與action、category并稱為android元件的3大過濾機制(将在6.6節詳細介紹)。但data與後兩者不同的是并不是簡單地通過字元串對比的方式進行比對,而是按着一定規則進行比對。實際上,data本身又分為兩種方式進行比對:mime type和uri。
mime type就是指要通路的元件處理的資料類型,例如video/mpeg4、video/mp4、video/avi等。mime type也可以用通配符()比對某一類型的資料,例如“audio/”表示所有的音頻資料格式。
uri有些類似我們經常使用的web位址,但要比web位址範圍更廣,例如,下面的3行字元串都屬于uri。
設定mime type和uri可以由下面幾個方法完成,通過這些方法可以單獨設定這兩個值,也可以同時設定這兩個值。
1.settype方法
該方法的原型如下:
settypeandnormalize與settype的功能類似,也用于設定mime type,并且将uri清空。但settypeandnormalize方法還可以規範mime type。例如,如果mimi type設為“text/plain; charset=utf-8”,就會将後面的非mimi type部分去掉,變成“text/plain”。該方法還可以使mimi type的寫法看起來更标志,例如會将“text/x-vcard”變成“text/x-vcard”。
其實settypeandnormalize隻是調用了intent.normalizemimetype方法對mimi type進行規範處理。settypeandnormalize方法的代碼如下:
5.setdataandtype方法
該方法用于同時設定uri和mime type,原型如下:
下面的代碼同時設定了uri和mime type。
6.setdataandtypeandnormalize方法
該方法用于同時設定uri和mime type,并且将uri和mime type标準化,該方法的原型如下:
6.2.6 附加資料(extra)
extra就是一些key-value資料對。這些資料通過intent類提供的具有多個重載形式的putextra方法設定。例如,下面是putextra方法的一些常用的重載形式。
盡管通過data可以向要通路的元件傳遞一些資料,但對于資料量較大或需要将資料進行劃分時應使用extra。有很多系統的action需要提供附加資訊,例如action_timezone_changed就需要一個名為time-zone的附加資訊,是以在使用該action時需要使用下面的代碼設定附加資訊。
如果想知道哪一個系統action需要傳遞附加資訊,可以通過content assist(内容助手)來查詢。例如,要查詢action_timezone_changed需要哪些附加資訊,首先要找到該action,然後選中該action,就會在下方顯示該action的詳細資訊,如圖6-3所示的黑框中就是該action需要的附加資訊。
6.2.7 标志(flags)
flags和前幾種intent對象封裝的資訊都不同。flags既不會定位視窗,也不會向視窗傳遞資料,flags隻用來控制視窗顯示行為。這裡涉及任務(task)和回退棧(back stack)的概念。這一部分内容會在7.2節詳細讨論。在本章讀者隻要知道通過intent對象可以完成如下3項工作即可。
定位視窗:通過component name、action、category和data可以定位一個或多個視窗。
傳遞資料:通過data和extra。
控制通路元件的行為(視窗、服務和廣播):通過flags。
1就是androidmanifest.xml檔案中标簽的package屬性值。
2不僅視窗、服務和廣播接收器也可以與多個字元串進行綁定,由于本章主要介紹視窗的基礎知識,是以本章的大多數地方隻提到了視窗,但讀者要清楚一點,除非特别提到,否則後面章節介紹的服務和廣播接收器也擁有同樣的特性。關于如何将字元串與視窗綁定,會在本章後面的部分詳細介紹。
3當然,除了要有android.intent.action.main外,還需要定義一個叫android.intent.category.launcher的category。這部分内容會在本章後面的部分介紹。`