編輯:初級開發
Intent是一種運行時綁定(run-time binding)機制,它能在程序運行的過程中連接兩個不同的組件。通過Intent,你的程序可以向Android表達某種請求或者意願,Android會根據意願的內容選擇適當的組件來完成請求。比如,有一個Activity希望打開網頁浏覽器查看某一網頁的內容,那麼這個Activity只需要發出WEB_SEARCH_ACTION請求給Android,Android會根據Intent的請求內容,查詢各組件注冊時聲明的IntentFilter,找到網頁浏覽器Activity來浏覽網頁。 Intent是一種運行時綁定(run-time binding)機制,它能在程序運行的過程中連接兩個不同的組件。通過Intent,你的程序可以向Android表達某種請求或者意願,Android會根據意願的內容選擇適當的組件來完成請求。比如,有一個Activity希望打開網頁浏覽器查看某一網頁的內容,那麼這個 Activity只需要發出WEB_SEARCH_ACTION請求給Android,android會根據Intent的請求內容,查詢各組件注冊時聲明的IntentFilter,找到網頁浏覽器Activity來浏覽網頁。
Intent對象抽象地描述了要執行的操作,其描述的基本內容可以分為組件名稱、Action(動作)、Data(數據)、Category(類別)、Extra(附加信息)和Flag(標志位)6部分,下面是詳細的介紹。
(1) 組件名稱是指Intent目標組件的名稱。組件名稱是一個ComponentName對象,這種對象名稱是目標組件類名和目標組件所在應用程序的包名的組合。組件中包名不一定要和manifest文件
中的包名完全匹配。組件名稱是一個可選項。如果Intent消息中指明了目標組件的名稱,這就是一個顯式消息,Intent會傳遞給指明的組件。如果目標組件名稱並沒有指定,android則通Intent
內的其他信息和已注冊的IntentFilter的比較來選擇合適的目標組件。
(2) Action描述Intent所觸發動作名字的字符串,對於Broadcast Intent來說,Action指被廣播出去的動作。理論上Action可以為任何字符串,而與android系統應用有關的Action字符串以靜態字符串常量的形式定義在了Intent類中。列出了當前android系統中常見的Activity Action Intent的Action
ACTION_CALL 撥出Data裡指定的電話號碼
ACTION_EDIT 打開編輯Data裡指定數據相對應的應用程序
ACTION_MAIN 主程序入口,不會接收數據,結束後也不返回數據
ACTION_SYNC 在android平台和服務器之間同步數據
ACTION_VIEW 根據Data類型的不同,打開相對應的應用程序以顯示數據
ACTION_DIAL 啟動Dialer或其他撥號程序,並顯示Data裡指定的電話號碼
ACTION_SENDTO 向Data裡描述的目標地址發送數據
ACTION_TIME_TICK 系統時間每過一分鐘發出的廣播
ACTION_TIME_CHANGED 系統時間通過設置發生了變化
ACTION_TIMEZONE_CHANGED 時區改變
ACTION_BOOT_COMPLETED 系統啟動完畢
ACTION_PACKAGE_ADDED 新的應用程序apk包安裝完畢
ACTION_PACKAGE_CHANGED 現有應用程序apk包改變
ACTION_PACKAGE_REMOVED 現有應用程序apk包被刪除
ACTION_UID_REMOVED 用戶id被刪除
(3) Data描述Intent要操作的數據URI和數據類型。有的動作需要對相應的數據進行處理。比如,對於動作ACTION_EDIT來說,它的數據可以為聯系人、短信息等可編輯的URI。而對於
ACTION_CALL來說,它的數據可以是一個tel://格式的電話號碼URI。正確設置Intent的數據對於android尋找系統中匹配 Intent請求的組件很重要。如果你使用了ACTION_CALL,但是你的數據卻設置成了mailto://格式的URI,那麼你所期望的“啟動打電話應用程序”這一動作會因為沒有與之相對應的應用程序而不會被執行。所以每次使用Intent時,我們都應該留意與設置的Action相關的數據類型和格式。
(4) Category是對被請求組件的額外描述信息。android也在Intent類中定義了一組靜態字符串常量表示Intent不同的類別
(5) 列出了常用的Category常量
CATEGORY_BROWSABLE 目標Activity能通過在網頁浏覽器中點擊鏈接而激活(比如,點擊浏覽器中的圖片鏈接)
CATEGORY_GADGET 表示目標Activity可以被內嵌到其他Activity當中
CATEGORY_HOME 目標Activity是HOME Activity,即手機開機啟動後顯示的Activity,或按下HOME鍵後顯示的Activity
CATEGORY_LAUNCHER 表示目標Activity是應用程序中最優先被執行的Activity
CATEGORY_PREFERENCE 表示目標Activity是一個偏好設置的Activity
(5) Extra當我們使用Intent連接不同的組件時,有時需要在Intent中附加額外的信息,以便將數據傳遞給目標Activity。比如 ACTION_TIMEZONE_CHANGED需要帶有附加信息表示新的時區。Extra用鍵值對結構保存在Intent對象當中,Intent對象通過調用方法putExtras()和getExtras()來存儲和獲取Extra。Extra是以Bundle對象的形式來保存的,Bundle對象提供了一系列put和get方法來設置、提取相應鍵值信息。在Intent類中同樣為android系統應用的一些Action所附加信息的鍵值定義了靜態的字符串常量。
EXTRA_BCC 裝有郵件密送地址的字符串數組
EXTRA_CC 裝有郵件抄送地址的字符串數組
EXTRA_EMAIL 裝有郵件發送地址的字符串數組
EXTRA_INTENT 使用ACTION_PICK_ACTIVITY動作時裝有Intent選項的Key
EXTRA_KEY_EVENT 觸發該Intent的按鍵的KeyEvent對象
EXTRA_PHONE_NUMBER 使用撥打電話相關Action時,電話號碼字符串的Key,類型為String
EXTRA_SHORTCUT_ICON 使用ACTION_CREATE_SHORTCUT在HomeActivity創建快
...
對於明確指出了目標組件名稱的Intent,我們稱之為“顯式Intent”。對於沒有明確指出目標組件名稱的Intent,則稱之為“隱式Intent”。android系統使用Intent Filter 來尋找與隱Intent相關的對象.
顯式Intent直接用組件的名稱定義目標組件,這種方式很直接。但是由於開發人員往往並不清楚別的應用程序的組件名稱,因此,顯式Intent更多用於在應用程序內部傳遞消息。比如在某
應用程序內,一個Activity啟動一個Service。隱式Intent恰恰相反,它不會用組件名稱定義需要激活的目標組件,它更廣泛地用於在不同應用程序之間傳遞消息。
清楚了顯式Intent和隱式Intent的概念後,我們再來看看決定Intent目標組件的因素。在顯式Intent消息中,決定目標組件的唯一要素就是組件名稱,因此,如果你的Intent中已經明確定義了目標組件的名稱,那麼你就完全不用再定義其他Intent內容。而對於隱式 Intent則不同,由於沒有明確的目標組件名稱,所以必須由android系統幫助應用程序尋找與Intent請求意圖最匹配的組件。具體的選擇方法是:Android將Intent的請求內容和一個叫做Intent Filter的過濾器比較,Intent Filter中包含系統中所有可能的待選組件。如果Intent Filter中某一組件匹配隱式Intent請求的內容,那麼android就選擇該組件作為該隱式Intent的目標組件.
Android 如何知道應用程序能夠處理某種類型的Intent 請求呢? 這需要應用程序在androidManifest.XML中聲明自己所含組件的過濾器(即可以匹配哪些Intent請求)。一個沒有聲
明Intent Filter的組件只能響應指明自己名字的顯式Intent請求,而無法響應隱式Intent請求。而一個聲明了Intent Filter的組件既可以響應顯式Intent請求,也可以響應隱式Intent請求。在通過和Intent Filter比較來解析隱式Intent請求時,android將以下三個因素作為選擇的參考標准。
Action
Data
Category
而Entra和Flag在解析收到Intent時是並不起作用的。
Intent Filter
應用程序的組件為了告訴android自己能響應、處理哪些隱式Intent請求,可以聲明一個甚至多個Intent Filter。每個Intent Filter描述該組件所能響應Intent請求的能力——組件希望接收什麼類型的請求行為,什麼類型的請求數據。比如之前請求網頁浏覽器這個例子中,網頁浏覽器程序的Intent Filter就應該聲明它所希望接收的Intent Action是WEB_SEARCH_ACTION,以及與之相關的請求數據是網頁地址URI格式。
如何為組件聲明自己的Intent Filter? 常見的方法是在androidManifest.XML文件中用屬性
前面我們提到,隱式Intent和Intent Filter進行比較時的三要素是Intent的動作、數據以及類別。實際上,一個隱式Intent請求要能夠傳遞給目標組件,必要通過這三個方面的檢查。如果任何一方面不匹配,android都不會將該隱式Intent傳遞給目標組件。接下來我們講解這三方面檢查的具體規則。
1.動作測試
< intent-filter>元素中可以包括子元素,比如:
< 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請求或
(1) 如果
(2) 反之,如果Intent請求中沒有設定Action類型,那麼只要
2.類別測試
< intent-filter>元素可以包含
< intent-filter . . . >
< category android:name="android.Intent.Category.DEFAULT" />
< category android:name="android.Intent.Category.BROWSABLE" />
< /intent-filter>
只有當Intent請求中所有的Category與組件中某一個IntentFilter的
3.數據測試
數據在
< intent-filter . . . >
< data android:type="video/mpeg" android:scheme="http" . . . />
< data android:type="audio/mpeg" android:scheme="http" . . . />
< /intent-filter>
< data>元素指定了希望接受的Intent請求的數據URI和數據類型,URI被分成三部分來進行匹配:scheme、 authority和path。其中,用setData()設定的Inteat請求的URI數據類型和scheme必須與IntentFilter中所指定的一致。若IntentFilter中還指定了authority或path,它們也需要相匹配才會通過測試。
講解完Intent基本概念之後,接下來我們就使用Intent激活android自帶的電話撥號程序,通過這個實例你會發現,使用Intent並不像其概念描述得那樣難。
我首先從宏觀的角度觀察Binder,Service,Service Manager,並闡述各自的概念。從Linux的概念空間中,android的設計Activity托管
外特性空間的Activity 我們先來看看,Android應用開發人員接觸的外特性空間中的Activity,對於AMS (activ
android 有一種叫消息隊列的說法,這裡我們可以這樣理解:假如一個隧道就是一個消息隊列,那麼裡面的每一部汽車就是一個一個消息,這裡我們先忽略掉超車等種種因素,只那麼
很多初入android或Java開發的新手對Thread、Looper、Handler和Message仍然比較迷惑,衍生的有HandlerThread、Java.uti