Android Google官方文檔(cn)解析之——Intents and Intent filter

  應用程序核心組件中的三個Activityservice,還有broadcast receiver都是經過一個叫作intent的消息激活的。Intent消息傳送是在相同或不一樣的應用程序中的組件之間後運行時綁定的一個設施。Intent對象也就是它本身是一個數據結構,這個數據結構持有將要執行操做的抽象描述,或者在broadcast的狀況下,是一個已經發生而將要宣佈的描述。爲傳遞intent到每一個不一樣類型的組件有單獨的機制:html

  • 一個Intent對象被傳遞到Context.startActivity()或是Activity.startActivityForResult()方法來啓動一個Activity或是獲得一個已經存在的Activity來作一些新的事情。(也能夠被傳遞到Activity.setResult()來返回到一個叫作startActivityForResult()Activity)android

  • 一個Intent對象被傳遞到Context.startService()來初始化一個service或是傳遞一個新的指令到一個已經運行的service。一樣的,一個Intent也能夠被傳遞到Context.bindService()來創建調用組件與目標服務之間的鏈接。還能夠隨意的初始化一個沒有運行的service
  • 傳遞給broadcast的方法中的任意一個方法(例如Context.sendBroadcast(),Context.sendOrderedBroadcast或是Context.sendStickyBroadcast())Intent對象被傳送給全部感興趣的廣播接收者。

  在那樣的狀況下,Android系統將找到適當的Activityservice或是broadcast receiver集合來響應這個Intent,若是有必要的話還會實例化它們。那些消息系統內沒有重疊部分:broadcast Intent只對應broadcast receiver,而不會給Activity或是service。一個傳遞給startActivity()方法的Intent只會被傳遞給一個Activity,毫不會傳遞給一個service或是broadcast receiver,等等。瀏覽器

  這份文檔開始於Intent對象的描述。而後會描述Android映射Intent到組件使用的法則,講述了哪個組件應當接受一個Intent消息。對於Intent來講並無準確的指明一個目標組件,進程將潛心於檢測Intent與關聯了潛在的目標組件的Intent filters安全

Intent Objects | Intent對象

  一個Intent對象是一個信息束。它容納了接受Intent組件感興趣的信息(例如將要執行的動做還有將要對其起做用的數據)加上Android系統感興趣的信息(好比應當處理這個Intent的組件的種類還有如何啓動目標Activity的指令)。主要地它能包含如下幾點:網絡

Component name | 組件名數據結構

  應當處理Intent組件的名字。這個字段是一個ComponentName對象,全部有資格的目標組件類名(例如」com.example.project.app.FreneticActivity」)集合還有應用程序manifest文件中應用程序所在的包名(例如」com.example.project」)集合。組件名和包名集合中的包在manifest中不是必須必定要匹配的。app

  組件名是可選的。若是被設置了,Intent對象會被傳送給指定類的實例。若是沒有設置組件名,Android系統會使用Intent對象中的其餘信息來定位一個合適的目標,在後文中請查看關於Intent Resolution.ide

  組件名能夠經過setComponent(),setClass,或是setClassName方法來設置,也能夠經過getComponent()方法來讀取。測試

Action |動做google

  一個字符串命名了將要執行的動做—或者是在broadcast Intent的狀況下,已經發生將要報告的動做。

  Intent類定義了一系列的動做常量,包括這些:

 

Constant 

常量

Target component 

目標組件

Action

動做

ACTION_CALL

activity

Initiate a phone call.

初始化一個打電話界面

ACTION_EDIT

activity

Display data for the user to edit.

爲用戶展現數據來編輯

ACTION_MAIN

activity

Start up as the initial activity of a task, with no data input and no returned output.

做爲任務的初始化Activity啓動,沒有數據輸入也沒有返回值輸出。

ACTION_SYNC

activity

Synchronize data on a server with data on the mobile device.

 

ACTION_BATTERY_LOW

broadcast receiver

A warning that the battery is low.

提示電量太低。

ACTION_HEADSET_PLUG

broadcast receiver

A headset has been plugged into the device, or unplugged from it.

耳機已經被插入設備或是從設備上拔出。

ACTION_SCREEN_ON

broadcast receiver

The screen has been turned on.

屏幕被轉向。

ACTION_TIMEZONE_CHANGED

broadcast receiver

The setting for the time zone has changed.

時區設置被改變。

  查看預約義的類內部動做常量列表請看Intent的類描述。其餘的action被定義在Android API的其餘地方。你也能夠在應用程序中爲激活組件定義你本身的動做字符串。你創造的action 常量應當包括包名做爲前綴-例如:」com.example.project.SHOW_COLOR」。

  動做主要的決定了Intent的其餘部分是如何構造的,尤爲是」data」還有」extras」字段,做爲方法名決定參數列表還有返回值。由於這樣,使用盡量特殊的action名還有將他們與Intent中的其餘字段名結合的緊一點是一個好主意。換句話來講,爲Intent對象定義一整套協議而不是定義一個孤立action可以使你的組件更易於操做。

  在Intent對象中的動做被」setAction()」方法設置,也能經過」getAction()」方法來獲取。

Data | 數據

  被執行數據的URI還有數據的MIME類型。不一樣的動做會被不一樣種類的數據規格來組成一對。例如,若是動做字段是ACTION_EDIT,數據字段會包含將要被展現編輯文檔的URI。若是動做是ACTION_CALL,數據字段將會是包含tel:URI,將要撥打的電話。一樣的,若是動做是ACTION_VIEW而數據字段是一個http:URI,那麼接收的Activity將會被調用來下載或是展現URI表示的數據。

  當匹配一個Intent到能勝任處理數據的組件的時候,除了URI以外知道數據的類型(MIME type)也是很重要的。例如,展現圖像數據的組件不能被用做播放媒體文件調用。

在不少狀況下,數據類型能經過URI推斷出來尤爲是content:URIs,代表了數據是在設備上存放的,被content provider來控制(請查看content provider的分開討論)。可是類型也能夠在Intent對象中準確的設置。setData()方法僅僅指定數據的URIsetType()方法僅僅指定數據的MIME類型,而setDataAndType()方法能夠同時指定數據的URIMIME類型。URI能夠經過getData()方法獲取,類型能夠經過getType()獲取。

Category | 種類

  包含關於組件種類的額外信息的字符串能夠處理Intent。許多種類描述能夠放在Intent對象中。就像action同樣,Intent類定義了許多category常量,包括如下這些:

 

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

目標Activity能夠被瀏覽器安全的調用,經過一個連接來展現數據。例如一張圖片或是一條郵件消息。

CATEGORY_GADGET

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

Activity能夠被嵌入到另外一個主機產品的Activity中。

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.

這個Activity展現了主屏幕,設備被翻轉或是HOME鍵被按下的時候用戶看見的第一個界面。

CATEGORY_LAUNCHER

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

這個Activity能夠是一個任務的啓動Activity,在頂級應用程序啓動器中被列出。

CATEGORY_PREFERENCE

The target activity is a preference panel.

目標Activity是一個參數面板。

 

  爲所有的分類列表,請查看Intent類描述。

  addCategory()方法在Intent對象中任命一個種類,removeCategory()方法來刪除以前添加過的種類,getCategories()方法來獲取當前對象中的全部種類集合。

Extras | 額外部分

  額外信息的鍵值對,額外信息應當被分發處處理Intent的組件。正像一些action被特殊種類的URI配對,一些action也經過特殊的額外部分配對。例如,ACTION_TIMEZONE_CHANGED Intent有一個」time-zone」的額外部分,它定義了新的時區,ACTION_HADSET_PLUG有一個」state」額外部分代表了耳機如今是不是插入仍是拔出的狀態,也有一個」name」額外部分給耳機的類型。若是你要創造一個SHOW_COLORaction,顏色值將會在一個額外鍵值對中設置。

  Intent對象中有一系列的put...()方法來插入各類各樣的額外數據的類型還有相似的get...()方法集合來讀取這些數據。這些方法與Bundle對象中的方法是等價的。實際上,額外部分也能夠被安放和讀取做爲Bundle經過使用putExtras()方法和getExtras()方法。 

Flags | 標記

  不一樣種類的標記。不少標記介紹了Android系統如何啓動一個Activity(例如,Activity屬於哪個任務)還有在啓動以後如何對待它(例如,它是否屬於最近啓動的Activity列表)。全部的標記都定義在Intent類中。

  Android系統和伴隨着平臺的應用程序都使用Intent對象來發送系統原生廣播還有激活系統組件。查看如何構造Intent來激活系統組件,請在參考文獻中查閱list of intents.

Intent Resolution | Intent 解析

Intent 能夠被分爲兩大類:

  • 顯式的Intent經過組件的名字指定了目標組件(以前提到過的component name字段有值集合)。既然組件名通常來講不能被其餘應用程序的開發者所知道,準確的Intent是爲全局應用程序消息所使用的,例如一個Activity啓動一個從屬的service或是啓動一個同類型的Activity
  • 隱式的Intent並不命名目標(組件名字段爲空)。隱式的Intent常常用於激活其餘應用程序中的組件。

  Android傳遞顯式的Intent給一個指定的目標類的實例。Intent對象中除了組件名沒有其餘東西關心決定哪一個組件應該獲取到該Intent

  隱式的Intent須要不一樣的策略。在目標組件缺乏的狀況下,Android系統必須找到最好的組件(或是多個組件)來處理該Intent—單個的Activity或是service來執行請求的動做或是響應廣播通知的廣播接受者集合。它經過比較Intent對象的內容和Intent filter(一個關聯了潛在接收Intent的組件的結構)來作到。過濾器通知組件的能力還有劃定Intent能夠處理的界限。他們打開這樣一個組件,這個組件有可能接收已經通知了類型的隱式Intent。若是一個組件沒有Intent filters,那麼它只接受顯示的Intent。一個有過濾器的組件既能夠接收顯式的也能夠接收隱式的Intent

  一個Intent對象中只有三個方面被查閱,當Intent對象是針對於Intent filter測試的時候。ActionData(both URI and data type)Category

  Extra還有flag在解決組件接收Intent的時候並不起做用。

Intent filters

  爲了通知系統他們能處理哪個隱式的IntentActivityservicebroadcast receiver能夠有一個多更多的Intent filter。每個過濾器描述了組件的一個能力,一個罪案將會接收IntentIntent集合。,實際上,Intent filter在但願類型的Intent中過濾,當過濾掉不想要的Intent時,但只有不想要的隱式Intent(那些沒有指名一個目標類的Intent)。顯示Intent老是被傳遞到他的目標,無論它是否包含Intent filter;過濾器沒有被請教。可是隱式Intent傳遞給一個組件,只有Intent能傳遞給組件的過濾器之一的組件。

  一個組件中每個能作的工做有單獨的過濾器,每個能呈現給用戶的外觀。例如,記事本應用程序中的NoteEditor Activity有兩個過濾器:一個用來啓動用戶能夠查看或編輯的特定便籤,另外一個來開始一個新的空白便籤,那麼用戶能夠書寫和保存。(全部的Note Pad的過濾器將在以後的Note Pad Example部分描述。)

  Intent filterIntentFilter類的實例。然而,既然Android系統必須在啓動一個組件以前就得必須瞭解組件的能力,那麼Intent filter通常來講不在Java代碼中設置,而是在應用程序的manifest文件(AndroidManifest.xml)中做爲<intent-filter>元素來定義。(有一個例外,經過調用Context.registerReceiver()方法動態註冊的廣播接收者,他們是做爲intentFilter對象直接建立的)

  過濾器有與actiondatacategory字段平行的Intent對象字段。隱式Intent在全部三個方面對過濾器進行測試。爲了傳遞給擁有過濾器的組件,它必須經過全部的三項測試。若是即便沒有經過他們中的一個,Android系統都不會傳遞到組件,至少不在那個過濾器的基礎上。然而,即便一個組件有多個Intent filter,沒有經過組件過濾器的Intent也可能在另外一個上經過。

  三項測試將在下面被詳細的描述:

Action test | 動做測試

manifest文件中的<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,過濾器也須要列出多於一個的actionAction列表不能爲空,過濾器列表必須包含至少一個<action>標籤不然的話它將阻塞全部的Intent

  爲了經過這個測試,在Intent對象中指定的action必須與過濾器列表中的某一個action匹配。若是Intent對象或是過濾器沒有指定一個action,結果就是如下列出的:

  • 若是過濾器沒有列出actionIntent將不會匹配到任何東西,因此全部的Intent都不能經過測試。沒有Intent能夠經過該過濾器。
  • 另外一方面,沒有指定actionIntent對象將自動的經過測試,只要過濾器包含至少一個action

Category test | 種類測試

<intent-filter>元素也列出了category做爲子元素。例如:

<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測試,在Intent對象中的每個種類必須匹配過濾器中的category。過利器能夠列出附加的category,可是不能遺漏Intent中的任意一個category

  所以,原則上一個沒有種類的Intent對象老是能經過category測試,無論過濾器中有什麼。大部分狀況下那是對的。然而有一個例外,Android讓全部的隱式Intent經過startActivity()方法,好像他們包含至少一個種類:」android.intent.category.DEFAULT」(CATEGORY_DEFAULT常量)。所以,將要接收隱式IntentActivity必須在他們的Intent過濾器中包含」android.intent.category.DEFAULT」。(」android.intent.action.MAIN」還有」android.intent.category.LANCHER」設置的過濾器除外,他們標記了一個開始新任務的Activity而後在啓動器中呈現出來。他們能夠在category列表中包含」android.intent.category.DEFAULT」,可是不是必須的。)查看更多的那些過濾器的信息能夠參見以後提到的Using intent matching

Data test | 數據測試

  就像action還有category同樣,一個Intent filter的數據規格也是在一個子元素中包含的。在那些狀況下這個子元素能夠出現屢次或是不出現。例如:

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

  每個<data>元素能夠指定一個URI還有一個數據類型(MIME 媒體類型)。有單獨的屬性——schemehost,還有path——每個URI的不一樣部分:scheme://host:port/path

  例如,在接下來的URI中,content://com.example.project:200/folder/subfolder/etcscheme」content」,host」com.example.project」,port」200」,path」folder/subfolder/etc」。Host還有port在一塊兒組成了整個URI,若是一個host沒有被指定,那麼port就會被忽視。

  那些屬性中每個都是可選的,但他們彼此之間互不依賴。authority是有意義的,scheme必須被指定。爲了一個地址是有意義的,schemeauthority都必須被指定。

  當Intent對象中的URI被與filter中的URI詳述比較時,實際上只會與filter中提到的URI部分比較。例如,若是一個過濾器只指定了scheme,全部擁有該schemeURI將會匹配這個過濾器。若是一個過濾器指定了scheme還有authority可是沒有指定path,全部有相同scheme還有authorityURI能匹配,無論他們的path。若是一個過濾器指定了schemeauthority,還有path,只有有相同schemeauthority還有path的能夠匹配。然而,在過濾器中path詳細會包含通配符,只須要path的局部匹配。

  <data>元素的」type」屬性指定了數據的MIME類型。在過濾器中它比URI更常見。Intent對象還有過濾器均可以用」*」做爲子類型的萬能類型,例如」text/*」或是」audio/*」代表任意子類型的匹配。

數據測試比較URI還有Intent對象中的數據類型和過濾器中的URI還有數據類型。過則以下:

  1. 既沒有URI也沒有數據類型的Intent對象只有在過濾器沒有指明URI還有數據類型的狀況下才能經過測試。
  2. URI可是沒有數據類型的(URI中也不能推斷出類型)Intent對象只有它的URI匹配了過濾器的URI,這個過濾器並無指明一個類型。這將只會是這樣的狀況,像」mailto:」還有」tel:」同樣的URI,它們並不涉及到實際的數據。
  3. 有數據類型可是沒有URIIntent對象只有在過利器列出了一樣的數據類型一樣的也沒有指明URI的狀況下能經過測試。
  4. 既有URI也有數據類型(或是從URI中可用推斷出數據類型)Intent對象,只有在它的類型匹配了過濾器中的一個類型才能經過測試的數據類型部分。若是它的URI匹配了過濾器中的一個URI或者它有」content:」或是」file:」URI而且過濾器沒有指明URI的狀況才才能公國測試的URI部分。換句話來講,組件是默認支持」content:」還有」file」數據的若是過濾器值列出了數據類型。

  若是Intent能夠經過多於一個的Activity或是service的過濾器,那麼用戶將會被詢問激活哪個組件。若是沒有目標組件被找到那麼會引起一個異常。

Common cases | 一般狀況

  上面提到最後一條數據測試的規則,反應了組件可以從文件或是content provider中獲取本地數據的指望。所以,它們的過濾器只須要列出數據類型而沒必要要準確的命名」content:」和」file:」scheme.這是一個經典的案例。好比一個<data>元素像下面說的這樣告訴Android組件能夠從content provider中獲取圖像數據而且展現它:

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

  既然大部分的有效數據都是被content provider所提供,那麼指明瞭數據類型可是沒有URI的過濾器或許是最多見的。

  另外一個常見的配置是有scheme還有數據類型的過濾器。例如像下面的<data>元素告訴Android塑件能夠從網絡中獲取視頻數據而且展現它:

<data android:scheme="http" android:type="video/*" />

  例如考慮當用戶跟隨了一個網頁上的連接,瀏覽器程序作什麼呢。它開始嘗試展現數據(若是連接是一個HTML頁面)。若是不能展現該數據,它將含有這個scheme的隱式Intent還有數據類型放在一塊兒而後嘗試打開一個能作這個任務的Activity。若是沒有接收者,那麼它請求下載管理器來下載該數據。那將把它放在content provider的管理下,那麼有大量的Activity(那些只命名了數據類型的過濾器)能夠響應。

  大部分的應用程序也只有一種方法來初始啓動,在沒有任何特殊數據引用的狀況下。能初始化應用程序的Activity有被做爲action」android.intent.action.MAIN」的過濾器。若是他們要被放在應用程序啓動器中,他們也須要指定」android.intent.category.LAUNCHER」category:

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

Using intent matching | 使用Intent匹配 

  Intent匹配Intent過濾器不只是爲了發現目標組件來激活,並且發現一些設備上的組集合的一些東西。好比,Android系統居住於應用程序啓動器中,爲用戶來展現可用的應用程序並啓動的頂級視圖,經過找到全部定義了」android.intent.action.MAIN」action還有」android.intent.category.LAUNCHER」category過濾器的Activity。而後在啓動器中展現那些Activity的圖標還有標籤,經過查找在過濾器中帶有」android.intent.category.HOME」的Activity來展現home屏幕。

  你應用程序使用Intent匹配也是相似的方式。包管理器(PackageManager)有一系列的query...()方法,它返回你能夠接收特定Intent的全部組件,還有相似的一系列的resolve...()方法來決定響應Intent的最好組件。例如queryIntentActivities()返回能執行做爲參數傳過來Intent的全部Activity列表,queryIntentServices()返回一個相似的服務列表。這些方法並不激活組件,他們僅僅列出了能響應Intent的組件列表。對於broadcast receiver來講也有相似的方法,queryBroadcastReceivers().

 

Note Pad Example | 記事本例子

  記事本示例程序可讓用戶瀏覽便籤列表,能夠查看列表中的單獨項的詳細信息,編輯項,添加新項到列表中。這個章節將查看這個程序的manifest文件中的Intent filter(若是你在SDK離線狀況下工做,你能夠查看到這個示例程序的全部源碼,包括manifest文件在<sdk>/sample/NotePad/index.html中。若是你是在線瀏覽這份文檔,源文件能夠在Tutorials and Sample Code 章節中看到)

  在這份manifest文件中,記事本應用程序定義了三個Activity,每個都擁有至少一個Intent filter。也定義了一個管理Note數據的content provider。這是整個的manifest文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.android.notepad">
    <application android:icon="@drawable/app_notes"
                 android:label="@string/app_name" >

        <provider android:name="NotePadProvider"
                  android:authorities="com.google.provider.NotePad" />

        <activity android:name="NotesList" android:label="@string/title_notes_list">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <action android:name="android.intent.action.EDIT" />
                <action android:name="android.intent.action.PICK" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.GET_CONTENT" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
            </intent-filter>
        </activity>
        
        <activity android:name="NoteEditor"
                  android:theme="@android:style/Theme.Light"
                  android:label="@string/title_note" >
            <intent-filter android:label="@string/resolve_edit">
                <action android:name="android.intent.action.VIEW" />
                <action android:name="android.intent.action.EDIT" />
                <action android:name="com.android.notepad.action.EDIT_NOTE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.INSERT" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
            </intent-filter>
        </activity>
        
        <activity android:name="TitleEditor" 
                  android:label="@string/title_edit_title"
                  android:theme="@android:style/Theme.Dialog">
            <intent-filter android:label="@string/resolve_title">
                <action android:name="com.android.notepad.action.EDIT_TITLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.ALTERNATIVE" />
                <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
            </intent-filter>
        </activity>
        
    </application>
</manifest>

  第一個Activity NotesList 與其餘Activity區分開來其實是它是在一個Note的文件夾(note列表)上操做而不是單個Note。它通常做爲進入應用程序的初始化用戶界面。它經過三個Intent過濾器的描述能作三件事情:

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

  這個過濾器定義了進入記事本應用程序的主入口。標準的」MAIN」 action是一個入口,不須要Intent中的任何其餘信息(例如沒有數聽說明),而後」LAUNCHER」category代表入口點會在應用程序啓動器中列出來。

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.PICK" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>

  這個過濾器聲明瞭這個Activity能在一個Note文件夾作的事情。它能夠容許用戶查看或是編輯文件夾(經過」VIEW」還有」EDIT」動做),或是從文件夾中選擇一個特別的Note(經過」PICK」動做)

  <data>元素的」mimeType」屬性指明瞭action操做的數據類型。它代表了Activity能夠從持有Note pad數據(vnd.google.note)content provider中獲取到一個大於零的遊標或是更多的項目(vnd.android.cursor.dir)。啓動ActivityIntent對象能夠包含一個內容:URI指明瞭Activity應該打開的這種類型的額外數據。

  在Note」DEFAULT」category在過濾器中也被提供了。它在這是由於Context.startActivity還有Activity.startActivityForResult()方法視全部的Intent都有」DEFAULT」category,可是有兩個除外:

  • 顯示指出了目標ActivityIntent
  • 包含」MAIN」action還有」LAUNCHER」categoryIntent

  所以,」DEFAULT」category對於全部的過濾器都是須要的,除了那些有」MAIN」action還有」LAUNCHER」category的過濾器。(intent filter 並不爲顯示Intent諮詢)

<intent-filter>
    <action android:name="android.intent.action.GET_CONTENT" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>

  這個過濾器描述了該Activity的能力來返回一個用戶選擇的Note,而用戶沒有要求文件夾中應當選擇的任意的詳述。」GET_CONTENT」動做相似」PICK」動做。兩種狀況下,Activity都從用戶選擇的Note中返回一個URI(在那種狀況下,URI被返回給Activity經過一個叫作startActivityForResult()來啓動便籤列表activity)這裏,然而調用者指定了但願的數據類型而不是用戶將要選擇的數據文件夾。

  數據類型,」vnd.android.cursor.item/vnd.google.note」,代表了該Activity能夠返回的數據類型,單個NoteURI。從返回的URI中,調用者能夠從持有Note pad數據(vnd.google.note)content provider中獲得一個準確項(vnd.android.cursor.item)的遊標。

  換句話說,在以前的filter」PICK」action,數據類型代表了Activity可以展現給用戶的數據的類型。在」GET_CONTENT」過濾器中,它代表了Activity也能夠返回數據的類型給調用者。

考慮到這些功能,下面的Intent將解決在NotesList activity

Action:android.intent.action.MAIN
啓動沒有指明數據的Activity

Action:android.intent.action.MAIN
Category:android.intent.category.MAIN
啓動沒有選擇數據指明的Activity。這是被頂級列表中的啓動器所使用的實際Intent。全部匹配了這個action還有category的filter的Activity都會被添加到啓動器。

Action:android.intent.action.VIEW
Data:content://com.google.provider.NotePad/notes
請求Activity展現」content://com.google.provider.NotePad/notes」下的全部note的列表。用戶能夠瀏覽note列表也能夠從中獲取到項的信息。

Action:android.intent.PICK
Data:content://com.google.provider.NotePad/notes
請求展現在」content://com.google.provider.NotePad/notes」下的note列表。用戶能夠從列表中選擇一項而後Activity會返回該項的URI給啓動NoteList Activity的Activity。

Action:android.intent.action.GET_CONTENT
Data type:vnd.android.cursor.item/vnd.google.note
請求Activity提供Note pad數據中的一項數據。

  第二項ActivityNoteEditor,展現用戶一個Note實體並且容許用戶編輯。它作兩件事就像在他的兩個Intent filter中描述的那樣:

<intent-filter android:label="@string/resolve_edit">
    <action android:name="android.intent.action.VIEW" />
    <action android:name="android.intent.action.EDIT" />
    <action android:name="com.android.notepad.action.EDIT_NOTE" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>

  首先Activity主要的目的是讓用戶在單個Note上查看或是編輯它。(「EDIT_NOTE category」對於」EDIT」來講是同義的。)Intent包含匹配了數據的URI,該URI匹配了MIME類型」vnd.android.cursor.item/vnd.google.note」,那就是說這個URI是一個特定noteURI。它會是被NoteList activity」PICK」或是」GET_CONTENT」動做返回的URI

  就像以前說的,過濾器列出」DEFAULT」種類以便於該Activity能夠被沒有明確指出NoteEditor類的Intent啓動。

<intent-filter>
    <action android:name="android.intent.action.INSERT" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>

  該Activity的第二個目的是確保用戶能夠建立一個新的便籤,新的便籤將會插入到已有的便籤文件夾中。該Intent將會包含匹配了」vnd.android.cursor.dir/vnd.google.note」MIME類型的URI,也就是說,便籤將會被放入的文件夾的URI

  考慮到這些功能,Intent將解決NoteEditorActivity以下:

action: android.intent.action.VIEW 
data: content://com.google.provider.NotePad/notes/ID
請求Activity展現被id定義的note的內容。(關於content:URI 如何指定集合中單個的成員,請查看 content provider)

action: android.intent.action.EDIT 
data: content://com.google.provider.NotePad/notes/ID
請求Activity展現沒有被id定義的note,而且讓用戶編輯它。如何用戶保存了更改,該Activity將會在content provider中更新note的數據。

action: android.intent.action.INSERT 
data: content://com.google.provider.NotePad/notes
請求Activity建立一個新的空白便籤在」content://com.google.provider.NotePad/notes」便籤列表中,並且容許用戶編輯它。若是用戶保存了便籤,那麼便籤的URI將會返回給調用者。

  最後一個ActivityTitleEditor,確保用戶能夠編輯便籤的標題。在沒有用Intent filter的狀況下經過直接調用Activity(經過在Intent中顯示的設置它的組件名)的方式也能被執行。可是這裏咱們抓住機會來展現如何在已經存在的數據上發佈可選擇的操做:

<intent-filter android:label="@string/resolve_title">
    <action android:name="com.android.notepad.action.EDIT_TITLE" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.ALTERNATIVE" />
    <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>

  該Activity只有一個Intent filter用了一個叫作」com..android.notepad.action.DEIT_TITLE」的用戶action.它必須在特定的note(數據類型爲」vnd.android.cursor.item/vnd.google.note」)上被調用,就像以前的」VIEW」還有」EDIT」動做同樣。然而這裏,該Activity展現了note數據中的標題,而不是note的內容自己。

  此外提供了一般的」DEFAULT」category,標題的編輯者也提供了兩個其餘的categories:」ALTERNATIVE」還有」SELECTED_ALTERNATIVE」。這些categories指出Activity能夠在選項菜單中呈現給用戶(就像」LAUNCHER」category肯定了應用程序啓動器中呈現給用戶的Activity)。注意到過濾器也提供了一個明確的標籤(經過android:label=」@string/resolve_title」)以更好的控制用戶看到的東西,當呈現了這個Activity做爲一個對他們正在查看的數據可選的動做。(更多關於那些categories還有建立選項菜單,請查看PackageManager.queryIntentActivityOptions()還有Menu.addIntentOptions()方法)

考慮到這些功能,接下來的Intent將在TitleEditor Activity中解決:

action: com.android.notepad.action.EDIT_TITLE 
data: content://com.google.provider.NotePad/notes/ID
請求Activity展現關聯note ID的標題,而且容許用戶編輯這個標題。
相關文章
相關標籤/搜索