Android——Intent和Intent過濾器

weixin_34120274發表於2016-07-23

http://www.cnblogs.com/XP-Lee/p/3613830.html

Intent就是一個啟用元件的訊息物件,用於元件之間的通訊。需要注意的是,能被Intent啟用通訊的元件只有三類:Activity、Service和BroadcastReceiver。對應這三類元件,Intent有下面三種使用場景:

  • 啟動Activity:在app中,一個Activity就代表一個使用者介面。以Intent為引數呼叫startActivity()啟動一個Activity例項。這個Intent告訴Activity去啟動,並且傳遞了一些必要資料給它。在Activity結束時,如果想要從這個結束的Activity接收資料,可以使用startActivityForResult()啟動,這樣在你的Activity的 onActivityResult()回撥就會接收到單獨的結果Intent。
  • 啟動Service:Service沒有使用者介面,它的職責就是在後臺執行操作。以Intent為引數呼叫startService()啟動一個Activity例項。這個Intent告訴Service去啟動,並且傳遞了一些必要資料給它。如果Service被設計成C/S結構的Server,你可以在其它元件中以Intent為引數呼叫bindService()繫結這個Service。
  • 傳送廣播:一個廣播訊息是可以被任何app接收的。系統為各種系統事件傳送廣播,你也可以傳送廣播( sendBroadcast()sendOrderedBroadcast(), or sendStickyBroadcast())。

上述這些Intent傳遞,不會有重疊。廣播Intent僅被傳遞給Receiver,永遠不會給Activity或者Service;一個傳送給Activity的Intent是隻會被傳遞給Activity,永遠不會給一個Service或Receiver;如此類推。

Intent型別(Intent Types)


Intent有兩種型別:

  • 顯式Intent:使用全類名啟動一個元件。顯示Intent啟動元件是在你自己的app當中的,因為需要知道一個元件的類名。
  • 隱式Intent:不實用類名,而是通過action去啟動。隱式Intent啟動的元件允許來自於另一個app。

顯式Intent啟動,Android系統可以通過這個Intent物件立即啟動元件。

隱式Intent啟動,Android系統會將Intent的內容與裝置所有app的manifest檔案中的Intent過濾器比較,找出最合適的元件去啟動。如果Intent和Intent過濾器匹配,系統就會啟動元件並且傳遞Intent物件。如果有多個Intent過濾器匹配,系統會顯示一個對話方塊,供使用者選擇使用哪一個app。(注,Intetn過濾器是manifest中的一個符號,指明一個元件可以接收什麼樣的Intent。)

上圖為隱式Intent啟動Activity的過程。【1】Activity A通過action建立一個Intent,讓後以這個Intent為引數呼叫startActivity()。【2】Android系統會隱式Intent,搜尋匹配所有app的Intent過濾。【3】系統匹配到Activity B,呼叫它的onCreate()方法並且傳遞Intent。

警告:為了確保app的安全性,通常使用顯式Intent啟動Service,並且不給Service宣告Intetn過濾器。使用隱式Intent啟動Service是危險的,因為你不可能確定多少個Service會響應這個Intetn,並且使用者看不到哪個Service啟動了。

建立Intent(Building an Intent)


Intent的主要資訊如下:

Component name

啟動的元件名稱。

對於隱式啟動來說,Component name是可選的。但是對於顯示啟動來說,Component name是必須的資訊。沒有Component name資訊的Intent就是一個隱式的Intent,系統會基於Intent的其它資訊(比如action、data、category)決定哪個元件來接收Intent。

Action

執行通用操作的字串。

系統框架提供了許多action常量,下標列出部分內容:

常量 目標元件 Action
ACTION_CALL Activity 打電話
ACTION_SCREEN_ON BroadcastReceiver 螢幕開啟
ACTION_TIMEZONE_CHANGED BroadcastReceiver 時區變化

自定義action,應該儘量使用包名作為字首。比如:

1 static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";

Data

 被執行資料的URI和它的MIME型別。通常,不同的action會伴隨不同的資料型別。例如, 如果action為ACTION_EDIT, 那麼Data將包含待編輯的資料URI. 如果action為ACTION_CALL, Data將為tel:電話號碼的URI. 如果action為ACTION_VIEW, 則Data為http:網路地址的URI.

當建立一個Intent時,為資料指定一個MIME型別作為URI的補充,是非常必要的。比如,一個activity可以顯示圖片但是不能播放音訊(儘管圖片和音訊的URI是非常相似的)。因此,為資料指定一個MIME型別可以幫助Android系統找到最佳的元件接收Intent。

然而,MIME型別有時候可以通過特別的URI推測出來。比如content: URI,它表明資料位於裝置上面,並且資料是被ContentProvider控制的,這就使的資料的MIME型別對系統來說是可見的。

警告:如果想要設定URI和MIME型別,應該呼叫setDataAndType();而不是同時呼叫setData()setType(),因為它們會使彼此的值無效。

Category

一個附加資訊的的字串,包含了關於可以處理該Intent的元件種類資訊。一個Intent可以有多個Category,但是大多數Intent需要Category。下面是一些公共Category資訊:

常量 含義
CATEGORY_BROWSABLE 目標activity可以被瀏覽器安全的啟動,用來顯示連結應用的資料——比如,一張圖片或者一封郵件
CATEGORY_GADGET 這個activity可以被嵌入到另一個activity中
CATEGORY_HOME 這個activity電視home介面,即裝置開啟或者按Home鍵看到的第一個頁面
CATEGORY_LAUNCHER 這個activity可以作為task的初始activity,並且是被列應用程式啟動器中
CATEGORY_PREFERENCE 目標activity是一個選項皮膚

 

上面的內容(component name, action, data, and category)描述了Intent的典型特徵。通過讀取這些內容,Android系統可以決定哪個元件可以被啟動。

然而,Intent還可以攜帶一些額外資訊,這些額外資訊不會影響系統選取元件,這些額外資訊就是Extras和Flags。

Extras

Key-value形式的額外資訊。

Intent類定義了許多的EXTRA_* 常量的標準資料型別。如果要自定義extra keys,應該儘量使用包名作為字首:

1 static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";

Flags

flag被定義在Intent類中,它作為Intent的metadata(描述資料的資料)。flag可以告訴Android系統如何啟動一個activity(比如,這個activity屬於哪一個task),並且在啟動後如何管理這個activity(比如,這個activity是否屬於recent activities列表)。

使用待定Intent(Using a Pending Intent)


PendingIntent是對Intent的包裝。PendingIntent的主要目的是授予外部程式使用被包裝的Intent,好像Intent在自己的程式中執行。

pending intent的主要使用場景如下:

  • 使用者執行一個你的Notification相關的操作(Android系統的NotificationManager會執行這個Intent)。
  • 使用者執行一個你的App Widget相關的操作(Home screen app會執行這個Intent)。
  • 未來某一個特定時刻執行(Android系統的AlarmManager會執行這個Intent)。

由於Intent被設計成只有特定型別的元件(Activity、Service和BroadcastReceiver)才能處理,因此PendingIntent的建立也必須要基於這層考慮。建立PendingIntent時,必須根據元件型別的不同,分別呼叫對應的方法建立:

這些方法最好使用當前app的Context。更多的關於PendingIntent的使用,參考NotificationsApp Widgets的Api指南。

Intent解析(Intent Resolution)


當系統收到一個隱式Intent的時候,系統會通過比較Intent和Intent比較器尋找最佳的activity,系統基於以下三個方面來比較:

  • action
  • data(URI和資料型別——MIME)
  • category

Action test

一個Intent過濾器可以宣告零個或多個<action>元素。比如:

1 <intent-filter>
2     <action android:name="android.intent.action.EDIT" />
3     <action android:name="android.intent.action.VIEW" />
4     ...
5 </intent-filter>

 

相關文章