android學習筆記之Intent&Intent filter

來源:互聯網
上載者:User
Intents and Intent Filters

應用程式的三種核心組件—activity,service和broadcast receiver---通過訊息被啟用,這些訊息稱為intent。Intent訊息是用來在運行時對在相同或不同應程式中的兩個組件進行綁定的對象。Intent對象本身是一個包含了對一個要執行的操作的抽象描述的被動(passive)資料結構。在不同的組件之間傳遞intent有不同的機制:

  •  將一個intent傳遞給Contex.startActivity()或Activity.AtartActivityForResult()來運行一個新的activity或者獲得一個存在的activity來做些新的事情(也可以將其傳遞給Activity.setResult()來返回資訊,這些資訊是其他activity通過調用方法startActivityForResult()想擷取的結果)。
  •  可以將一個intent傳遞給Context.startService()來初始化一個service或者傳遞一個新的指令(instructions)給以一個(ongoing) service。相似的,可以將一個intent傳遞給Context.bindService()來在calling組件和目標service間建立聯絡。它可以隨意的初始化未啟動並執行service。
  •  將intent傳遞給任何broadcast的方法(如Context.sendBroadcast(),Context.sendOrderedBroadcast()或者context.sendStickyBroadcast())來傳遞給所有感興趣的broadcast receiver。許多broadcas源於系統內代碼。

 

在每種情況,Android系統都會找到合適的activity,service或者broadcast receiverl來回應intent,在需要的時候執行個體化。這些資訊系統沒有重疊:Broadcast intent只會被傳遞給broadcast receiver,絕不會傳遞給activity或service。

Intent對象

       一個Intent對象是一些資訊的包裹。它包含了要接收該intent的組件感興趣的資訊(如要執行的動作以及需要的資料),還包含了Android系統感興趣的附加資訊(如可以接收該intent的組件的類別以及如何載入一個目標activity的指令)。Intent主要包含以下內容:

 

組件的名稱

       要接收這個intent的組件的名稱。這個欄位(field)是一個ComponentName對象—一個類完整的名字(如"com.example.project.app.FreneticActivity")和在應用程式manifest檔案中設定的組件所屬的包名(如"com.example.project")的聯合。組件名是可選的。如果設定了組件名,Intent對象會傳遞給指定類的執行個體。如果沒有設定組件名,Android用在intent中的其他資訊來定位合適的目標。

       常用setComponent(),setClass()或setClassName()來設定組件名稱,用getComponent()來讀取組件名。

 

Action

       用一個字串來命名被執行的action。Intent類定義個一些action常量,如下:

常量

目標組件

執行的動作(Action)

ACTION_CALL

activity

初始化一個撥打電話

ACTION_EDIT

activity

顯示資料來讓使用者編輯

ACTION_MAIN

activity

開始一個tast的初始的activity,輸入資料,也不輸出返回

ACTION_SYNC

activity

將service中的資料與手機裝置中的資料同步。

ACTION_BATTERY_LOW

broadcast receiver

警告電量過低

ACTION_HEADSET_PLUG

broadcast receiver

耳機被出入或拔出裝置

ACTION_SCREEN_ON

broadcast receiver

螢幕關閉

ACTION_TIMEZONE_CHANGED

broadcast receiver

時區的設定改變

       其他的action聲明分布在Android API的他處。你也可以定義自己的action字串,這時需要將應用程式套件組合名作為你的action字串的首碼。如"com.example.project.SHOW_COLOR"。Action欄位很大程度上決定了intent其他的結構---特別是data欄位和extras欄位----如同函數名決定了形參和傳回值。因此使action名字儘可能的明確並與intent的其它欄位緊密聯絡是個好主意。

       通過setAction()設定intent的action,並用getAction()讀取。

 

Data

       要處理的資料的URI或MIME類型。不同的action配有不同的資料規範。比如說,如果action欄位是ACTION_EDIT,data欄位應該包含要顯示和編輯的文檔的URI,如果action欄位是ACTION_CALL,data欄位應該是一個tel:含有要呼叫的號碼的URI,如果action欄位是ACTION_VIEW,data欄位應該是一個http:接收activity將要下載和顯示的資料的URI。

當處理一個intent時,知道其除URI之外的資料類型(它的MIME類型)往往十分重要。比如說,一個可以顯示圖片的組件不能用來播放音樂。

       在很多情況下,資料的類型可以由其URI推斷出-----特別是content:URIs, 它指明了資料在一個裝置中並由content provider控制。但是類型也可以在Intent對象中明確的設定。setData()方法只指定了資料的URI,setType()方法指定資料的MIME類型,setDataAndType()方法設定資料了URI和MIME類型。可以用getData()獲得資料,用getType()獲得類型。

 

 

Category

 

 

       可以接收這個intent的組件的類別的字串。Intent對象中可以放置多個category字串。Intent類定義了一些,如下:

Constant

Meaning

CATEGORY_BROWSABLE

The target activity can be safely invoked by the browser to display data referenced by a link — for example, an image or an e-mail message.

CATEGORY_GADGET

The activity can be embedded inside of another activity that hosts gadgets.

CATEGORY_HOME

The activity displays the home screen, the first screen the user sees when the device is turned on or when the HOME key is pressed.

CATEGORY_LAUNCHER

The activity can be the initial activity of a task and is listed in the top-level application launcher.

CATEGORY_PREFERENCE

The target activity is a preference panel.

使用addCategory()方法將一個category設定到intent對象,removeCategory()刪除一個之前添加的category,getCategories()獲得當前intent對象裡的所有category。

Extras

       要傳遞給目標組件的以索引值對形式存在的附加資訊。正如一些action與資料URI配對使用,action也要與extras相匹配。比如,一個ACTION_TIMEZONE_CHANGED intent有一個"time-zone"extra來指明新的時區,一個ACTION_HEADSET_PLUG 有一個"state" extra來指明耳機是否被插入或拔出,以及"name" extra來指明耳機的類型。如果你想自訂一個SHOW_COLOR action,那顏色的值將被設定成extra索引值對。

       Intent對象有一系列的如同putXXX()或getXXX()方法來設定或取得不同類型的extra資料。這些方法類似於Bundle對象。事實上,extra可以作為Bundle對象被載入或讀取,使用putExtras()和getExtras()方法。

Flags

       各種各樣的Flags。許多指定了Android系統如何載入一個activity以及載入以後如何處理(如,是否屬於最近的activity的清單)。所有的flag都在Intent類中定義。

 

Intent 解決方案

Intent可以被分為兩組:

  • Explicit(明確的) intents 用目標組件的名字指派。因為其他程式的開發人員一般不知道該組件的名字,所以explicit intent常用於程式內部的訊息----例如一個activity啟動一個附屬的service或者載入一個兄弟activity。
  • Implicit intents 沒有指明組件的名字(component name欄位是空的)。常用於啟用其他程式的組件。

Android在將explicit intent傳遞給指定目標組件的類的執行個體時,Intent對象中的component name 欄位對確定那個組件應該接收該intent至關重要。

    另一種不同的策略需要implicit intents。因為沒有指定目標,Android系統必須找到最合適的組件來處理這個intent。---一個單獨的activity或者service來執行請求的action或者broadcast receiver來回應boardcast通告。用Intent對象的內容與intent flilter(與組件相關的用來接收intent的結構)。Filter公布組件的能力以及限制可以處理的intent。它們可以接收公布的類型的implicit
intents的組件開放。如果一個組件沒有任何intent filter,它只可以接收explicit intent。一個有filter的組件既可以接收implicit intents也可接收explicit intent。

Intent只有3個欄位在於intent flilter比對的時候起作用:action 、data ( URI 和 data type) 、category。extras 和 flags在解析哪個組件可以接收這個intent時不起作用。

Intent filter

為了通知系統何種implicit intents可以處理,activity,service和broadcast receiver可以有一個或者多個intent filter。每個intent filter描述了一個組件的能力以及它們願意接收的intent集合。接收它們需要的intent,並過濾掉不希望接收的intent(只是implicit intents)。explicit intent必然會傳遞給它的目標,無論其是否包含intent filter。

一個組件對每項工作都有單獨的fliter。

一個intent filter是一個IntentFilter類的執行個體。然而,因為Android系統在載入組件前必須知道這個組件的能力,所以intent filter常常不在java代碼中建立,而是在應用程式的manifest檔案(AndroidManifest.xml)中設定<intent-filter>元素。(一個例外是broadcast receiver的filter是調用Context.registerReceiver()來動態註冊的,它們直接作為IntentFilter對象建立)。

一個filter有類似於Intent對象的action, data和category 的欄位。一個被傳遞到該組件的implicit intent會被檢測是否匹配這3個欄位。一旦有一個不匹配Android系統就不會將該intent傳遞給組件。

3中測試的細節如下:

Action test

使用<intent-filter>的子項目<action>,例如:

<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,但是一個filter對象卻可以擁有多個action。一個filter必須包含至少一個<action>,否則它將阻斷所有的intent。

      為了通過這個測試,在Intent對象裡的acyion必須與filter裡的action列表中的一個匹配。如果intent對象或者filter未指定action,結果如下:

  • filter未指定action,所有的intent都不能通過
  • 一個intent未指定action則通過測試---只要filter包含至少一個<action>

Category test

<intent-filter . . . >    <category android:name="android.intent.category.DEFAULT" />    <category android:name="android.intent.category.BROWSABLE" />    . . .</intent-filter>

請注意前面章節介紹的action和category的常量不會用在manifest檔案。取而代之的是一個完整的字串值。比如說上面例子中的"android.intent.category.BROWSABLE"對應 CATEGORY_BROWSABLE 常量。類似的,"android.intent.action.EDIT"對應ACTION_EDIT常量。

一個intent想通過測試,它的所有category必須與filter的匹配。Filter可以含有額外的category,但是不能遺漏任何在intent中的category。

       原則上,一個沒有category的intent總是能通過測試,不用考慮filter中有什麼。然而有一個例外:如果implicit intents 有一個"android.intent.category.DEFAULT" category( CATEGORY_DEFAULT常量),Android會將它們傳遞給startActivity(),因此希望接收implicit intents的activity在filter中必須包含"android.intent.category.DEFAULT"。(擁有"android.intent.action.MAIN" and "android.intent.category.LAUNCHER"的filter是一個例外,它們表示activity開始了一個新的task,並在程式載入介面顯示了,它們可以包含一個"android.intent.category.DEFAULT",但是卻不需要這麼做)。

Data test

<data>子標籤,可以有多個或沒有。

<intent-filter . . . >    <data android:mimeType="video/mpeg" android:scheme="http" . . . />     <data android:mimeType="audio/mpeg" android:scheme="http" . . . />    . . .</intent-filter>

每個<data>元素可以指定URI和資料類型(MIME media type)。URI有一些單獨的屬性-- schemehostport, 和path 。

scheme://host:port/path

舉例說,下面的URI:

content://com.example.project:200/folder/subfolder/etc

以上所述的URI的各部分是:scheme是"content",host是"com.example.project",port是"200",path是"folder/subfolder/etc"。

host和port共同組成了URI authority(許可權)。如果host未指定,則port將被忽略。

       每個屬性都是可選的,但是它們並不獨立於其他屬性:為了authority有意義必須指定scheme,為了path有意義必須指定scheme和authority。

       當Intent對象的URI與filter中的URI對比時,只會比較filter中的URI的一部分。比如說,如果一個filter只指定了scheme,所有含有該scheme的URI都匹配這個filter。如果一個filter只指定了scheme和authority但是沒有path,所有含有該scheme和authority的URI都匹配這個filter,不用考慮path。如果filter指定了scheme, authority和path,只有Intent的URI的scheme,
authority和path都匹配時才可通過。然而,一個path中可以包含萬用字元來允許部分路徑的匹配。

      <data>元素的tyoe屬性指明了資料的MIME類型。在filter中要比URI更普遍。Intent對象和filter都可以在子類型欄位中使用”*”萬用字元---比如說"text/*"或"audio/*"--------標識所有的子類型匹配。

       Data測試會比較Intent對象和filter的URI和資料類型。規則如下:

A.     如果一個Intent對象既不包含URI也不包含資料類型,只有在filter既沒有指定URI沒有指定資料類型時才可通過測試。

B.     如果一個Intent對象包含URI但不包含資料類型(且資料類型不能從URI推斷出),只有在匹配了filter指定的URI並且filter沒有指定資料類型時才可通過測試。這些情況只適合像mailto:tel:這樣的沒有指向實際資料的URI

C.     如果一個Intent對象不包含URI但是包含資料類型,只有filter有相同的資料類型且沒有指定URI才可通過

D.     如果一個Intent對象既包含URI又包含資料類型(或者資料類型可以由URI推斷出),要通過測試必須:資料類型可以匹配,URI匹配或者filter支援 content: 或 file: 的URI且filter未指定URI。換句話說,當一個filter只有資料類型時,它被假定支援 content: 和 file:資料。

如果一個intent可以通過不止一個activity或者service,系統會詢問允許選擇哪個組件來處理。如果沒有匹配時一個exception會拋出。

 

一般的情況:

上面最後一條顯示的是測試和規則,反映了組件可以從檔案或content provider擷取局部(local)資料。因此,一個filter可以只是指定資料類型而不需要明確的命名 content: 和 file: scheme。這是一個典型的情況。比如說,如下的<data>元素告訴系統這個組件可以從content provider接收映像資料並顯示它。

<data android:mimeType="image/*" />

因為多數可用的資料由content provider分配,指定了資料類型而不指定URI的filter或許會最為普遍

另一種普遍的設定是指定了scheme 和資料類型的filter。比如說一個如下的<data>元素告訴系統這個組件可以從互連網獲得vedio並播放它。

 

考慮下:當使用者點擊一個網頁中的連結時,瀏覽器程式會怎麼做。它首先會試圖顯示資料,如果不能顯示資料,它會收集一個指定了scheme 和資料類型的implicit intent,並試圖啟動一個可以做這項工作的activity。如果沒有響應者,

它將要求下載管理員下載資料。這將有一個content provider來控制它,所以一個潛在的大量的activity(那些含有只指明了資料類型的filter的activity)可以回應。

       大多數應用程式可以不涉及任何特殊資料的情況下重啟。可以作為啟動應用程式的activity會指定其action為"android.intent.action.MAIN".如果它們在程式載入器中表示,它們會指定"android.intent.

<intent-filter . . . >    <action android:name="code android.intent.action.MAIN" />    <category android:name="code android.intent.category.LAUNCHER" /></intent-filter>

使用intent匹配:

將Intent與Intent filter匹配不僅用於發現目標組件來處理該intent,還用來發現在裝置上的組件的一些資訊。比

如說,Android系統為了確定哪些應用程式可以羅列在程式載入器或案頭上並可以讓使用者載入,它會搜尋所有帶有"android.intent.action.MAIN"action和"android.intent.category.LAUNCHER"category的intent filter的activity。然後將這些activity的表徵圖添加到應用程式載入器。類似的,為了發現主畫面,它會尋找帶有"android.intent.category.HOME"filter的activity。

       你的應用程式可以以相似的方式利用intent載入。PackageManager有一些queryXXX()方法來返回所有可以接收特定intent的組件。比如說, queryIntentActivities()方法返回所有可以執行作為參數傳遞的intent的activity。queryIntentServices()返回類似的service。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.