1. 程式人生 > >安卓API指南之Intent 和 Intent 過濾器

安卓API指南之Intent 和 Intent 過濾器

本系列的文章全部為學習摘要,不偏重各種細節展示,更多的是安卓體系重要節點的羅列,並適時加入少量自己的理解分析,以便能快速的回顧安卓體系結構和那些重要的技術點。

Intent 是一個訊息傳遞物件,您可以使用它從其他應用元件請求操作。儘管 Intent 可以通過多種方式促進元件之間的通訊,但其基本用例主要包括以下三個:

  • 啟動 Activity:通過將 Intent 傳遞給 startActivity(),您可以啟動新的 Activity 例項。Intent 描述了要啟動的 Activity,並攜帶了任何必要的資料。如果您希望在 Activity 完成後收到結果,請呼叫 startActivityForResult()。在 Activity 的 onActivityResult() 回撥中接收結果。

  • 啟動服務:通過將 Intent 傳遞給 startService(),您可以啟動服務執行一次性操作(例如,下載檔案)。如果服務旨在使用客戶端-伺服器介面,則通過將 Intent 傳遞給 bindService(),您可以從其他元件繫結到此服務。

  • 傳遞廣播:通過將 Intent 傳遞給 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast(),您可以將廣播傳遞給其他應用。

Intent 分為兩種型別:

  • 顯式 Intent:按名稱(完全限定類名)指定要啟動的元件。
  • 隱式 Intent :不會指定特定的元件,而是宣告要執行的常規操作,從而允許其他應用中的元件來處理它。Android 系統通過將 Intent 的內容與在裝置上其他應用的清單檔案中宣告的 Intent 過濾器進行比較,從而找到要啟動的相應元件。

Intent 過濾器是應用清單檔案中的一個表示式,它指定該元件要接收的 Intent 型別。 為了確保應用的安全性,啟動 Service 時,請始終使用顯式 Intent,且不要為服務宣告 Intent 過濾器。

構建 Intent–Intent 中包含的主要資訊如下:

  • 元件名稱 ComponentName:
    可選項,但也是構建顯式 Intent 的一項重要資訊。如需在應用中啟動特定的元件,則應指定該元件的名稱。可以使用 setComponent()、setClass()、setClassName() 或 Intent 建構函式設定元件名稱。

  • 操作Action
    指定要執行的通用操作(例如,“檢視”或“選取”)的字串。系統自帶了一些操作,比如ACTION_VIEW和ACTION_SEND;若要定義自己的操作,請確保將應用的軟體包名稱作為字首。 例如:
    static final String ACTION_TIMETRAVEL = “com.example.action.TIMETRAVEL”;

  • 資料Data和型別MIME
    引用待操作資料和/或該資料 MIME 型別的 URI(Uri 物件)。提供的資料型別通常由 Intent 的操作決定。要僅設定資料 URI,請呼叫 setData()。 要僅設定 MIME 型別,請呼叫 setType()。如有必要,您可以使用 setDataAndType() 同時顯式設定二者。注意 setData() 和 setType(),會互相抵消彼此的值。

  • 類別Category
    一個包含應處理 Intent 元件型別的附加資訊的字串。 您可以將任意數量的類別描述放入一個 Intent 中,但大多數 Intent 均不需要類別。您可以使用 addCategory() 指定類別。當不指定時,預設有CATEGORY_DEFAULT類別。

  • 附加資料Extra
    攜帶完成請求操作所需的附加資訊的鍵值對。傳遞的資料包括基本資料型別,String,實現序列化的資料和Bundle支援的資料。

  • 標誌Flag
    在 Intent 類中定義的、充當 Intent 元資料的標誌。 標誌可以指示 Android 系統如何啟動 Activity(例如,Activity 應屬於哪個任務),以及啟動之後如何處理(例如,它是否屬於最近的 Activity 列表)。比如FLAG_ACTIVITY_CLEAR_TOP,代表啟動新Activity時,會使任務棧中目標Activity之上的活動出棧。若棧裡無目標,則新建目標,無其它效果。

處理Intent:
使用者可能沒有任何應用處理您傳送到 startActivity() 的隱式 Intent。如果出現這種情況,則呼叫將會失敗,且應用會崩潰。要驗證 Activity 是否會接收 Intent,請對 Intent 物件呼叫 resolveActivity()。如果結果為非空,則至少有一個應用能夠處理該 Intent,且可以安全呼叫 startActivity()。 如果結果為空,則不應使用該 Intent。

  • 要公佈應用可以接收哪些隱式 Intent,請在清單檔案中使用 元素為每個應用元件宣告一個或多個 Intent 過濾器。每個 Intent 過濾器均根據 Intent 的操作、資料和類別指定自身接受的 Intent 型別。 僅當隱式 Intent 可以通過 Intent 過濾器之一傳遞時,系統才會將該 Intent 傳遞給應用元件。

  • 顯式 Intent 始終會傳遞給其目標,無論元件宣告的 Intent 過濾器如何均是如此。

Intent 解析
當系統收到隱式 Intent 以啟動 Activity 時,它根據以下三個方面將該 Intent 與 Intent 過濾器進行比較,搜尋該 Intent 的最佳 Activity.

  • Intent 操作
    要指定接受的 Intent 操作,Intent 過濾器既可以不宣告任何 元素,也可以宣告多個此類元素。要通過此過濾器,您在 Intent 中指定的操作必須與過濾器中列出的某一操作匹配。
  • Intent 資料(URI 和資料型別)
    要指定接受的 Intent 資料, Intent 過濾器既可以不宣告任何 元素,也可以宣告多個此類元素。每個 元素均可指定 URI 結構和資料型別(MIME 媒體型別)。 URI 的每個部分均包含單獨的 scheme、host、port 和 path 屬性:< scheme >://< host >:< port >/< path >。例如:content://com.example.project:200/folder/subfolder/etc
    在此 URI 中,架構是 content,主機是 com.example.project,埠是 200,路徑是 folder/subfolder/etc。

作者: 劉鹹尚

  • Intent 類別
    要指定接受的 Intent 類別, Intent 過濾器既可以不宣告任何 元素,也可以宣告多個此類元素。若要使 Intent 通過類別測試,則 Intent 中的每個類別均必須與過濾器中的類別匹配。反之則未必然,Intent 過濾器宣告的類別可以超出 Intent 中指定的數量,且 Intent 仍會通過測試。

另外,PackageManager 提供了一整套 query…() 方法來返回所有能夠接受特定 Intent 的元件。此外,它還提供了一系列類似的 resolve…() 方法來確定響應 Intent 的最佳元件。 例如,queryIntentActivities() 將返回能夠執行那些作為引數傳遞的 Intent 的所有 Activity 列表,而 queryIntentServices() 則可返回類似的服務列表。這兩種方法均不會啟用元件,而只是列出能夠響應的元件。 對於廣播接收器,有一種類似的方法: queryBroadcastReceivers()。