源碼解讀之Intent解讀

Intent在Android開發中,雖然他不是Android四大組件中的一個,但是他是四大組件通信的紐帶,在我感覺,Intent在開發中有時候比Service,廣播還重要,有的項目可以不用服務和廣播,內容提供者,但是Intent基本都是必不可少的,好的廢話不多說,開始解讀Intent

簡介

Intent 是一個消息傳遞對象,您可以使用它從其他應用組件請求操作;

作用

儘管 Intent 可以通過多種方式促進組件之間的通信,但其基本用例主要包括以下三個:

*啓動 Activity:
Activity 表示應用中的一個屏幕。通過將 Intent 傳遞給 startActivity(),您可以啓動新的 Activity 實例。Intent 描述了要啓動的 Activity,並攜帶了任何必要的數據。
如果您希望在 Activity 完成後收到結果,請調用 startActivityForResult()。在 Activity 的 onActivityResult() 回調中,您的 Activity 將結果作爲單獨的 Intent 對象接收。如需瞭解詳細信息,請參閱 Activity 指南。
*啓動服務:
Service 是一個不使用用戶界面而在後臺執行操作的組件。通過將 Intent 傳遞給 startService(),您可以啓動服務執行一次性操作(例如,下載文件)。Intent 描述了要啓動的服務,並攜帶了任何必要的數據。
如果服務旨在使用客戶端-服務器接口,則通過將 Intent 傳遞給 bindService(),您可以從其他組件綁定到此服務。如需瞭解詳細信息,請參閱服務指南。
*傳遞廣播:
廣播是任何應用均可接收的消息。系統將針對系統事件(例如:系統啓動或設備開始充電時)傳遞各種廣播。通過將 Intent 傳遞給 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast(),您可以將廣播傳遞給其他應用。

Intent 類型

Intent 分爲兩種類型:

*顯式 Intent:按名稱(完全限定類名)指定要啓動的組件。 通常,您會在自己的應用中使用顯式 Intent 來啓動組件,這是因爲您知道要啓動的 Activity 或服務的類名。例如,啓動新 Activity 以響應用戶操作,或者啓動服務以在後臺下載文件。
*隱式 Intent :不會指定特定的組件,而是聲明要執行的常規操作,從而允許其他應用中的組件來處理它。 例如,如需在地圖上向用戶顯示位置,則可以使用隱式 Intent,請求另一具有此功能的應用在地圖上顯示指定的位置。
創建顯式 Intent 啓動 Activity 或服務時,系統將立即啓動 Intent 對象中指定的應用組件。
創建隱式 Intent 時,Android 系統通過將 Intent 的內容與在設備上其他應用的清單文件中聲明的 Intent 過濾器進行比較,從而找到要啓動的相應組件。 如果 Intent 與 Intent 過濾器匹配,則系統將啓動該組件,並向其傳遞 Intent 對象。 如果多個 Intent 過濾器兼容,則系統會顯示一個對話框,支持用戶選取要使用的應用。

Intent 過濾器是應用清單文件中的一個表達式,它指定該組件要接收的 Intent 類型。 例如,通過爲 Activity 聲明 Intent 過濾器,您可以使其他應用能夠直接使用某一特定類型的 Intent 啓動 Activity。同樣,如果您沒有爲 Activity 聲明任何 Intent 過濾器,則 Activity 只能通過顯式 Intent 啓動。

注意:
爲了確保應用的安全性,啓動 Service 時,請始終使用顯式 Intent,且不要爲服務聲明 Intent 過濾器。使用隱式 Intent 啓動服務存在安全隱患,因爲您無法確定哪些服務將響應 Intent,且用戶無法看到哪些服務已啓動。從 Android 5.0(API 級別 21)開始,如果使用隱式 Intent 調用 bindService(),系統會引發異常。

這裏寫圖片描述

圖 中. 隱式 Intent 如何通過系統傳遞以啓動其他 Activity 的圖解:[1] Activity A 創建包含操作描述的 Intent,並將其傳遞給 startActivity()。[2] Android 系統搜索所有應用中與 Intent 匹配的 Intent 過濾器。 找到匹配項之後,[3] 該系統通過調用匹配 Activity(Activity B)的 onCreate() 方法並將其傳遞給 Intent,以此啓動匹配 Activity。

構建 Intent

Intent 對象攜帶了 Android 系統用來確定要啓動哪個組件的信息(例如,準確的組件名稱或應當接收該 Intent 的組件類別),以及收件人組件爲了正確執行操作而使用的信息(例如,要採取的操作以及要處理的數據)。

Intent 中包含的主要信息如下:

組件名稱
要啓動的組件名稱。
這是可選項,但也是構建顯式 Intent 的一項重要信息,這意味着 Intent 應當僅傳遞給由組件名稱定義的應用組件。 如果沒有組件名稱,則 Intent 是隱式的,且系統將根據其他 Intent 信息(例如,以下所述的操作、數據和類別)決定哪個組件應當接收 Intent。 因此,如需在應用中啓動特定的組件,則應指定該組件的名稱。

注:啓動 Service 時,您應始終指定組件名稱。 否則,您無法確定哪項服務會響應 Intent,且用戶無法看到哪項服務已啓動。

Intent 的這一字段是一個 ComponentName 對象,您可以使用目標組件的完全限定類名指定此對象,其中包括應用的軟件包名稱。 例如, com.example.ExampleActivity。您可以使用 setComponent()、setClass()、setClassName() 或 Intent 構造函數設置組件名稱。

操作
指定要執行的通用操作(例如,“查看”或“選取”)的字符串。
對於廣播 Intent,這是指已發生且正在報告的操作。操作在很大程度上決定了其餘 Intent 的構成,特別是數據和 extra 中包含的內容。

您可以指定自己的操作,供 Intent 在您的應用內使用(或者供其他應用在您的應用中調用組件)。但是,您通常應該使用由 Intent 類或其他框架類定義的操作常量。以下是一些用於啓動 Activity 的常見操作:

ACTION_VIEW
如果您擁有一些某項 Activity 可向用戶顯示的信息(例如,要使用圖庫應用查看的照片;或者要使用地圖應用查看的地址),請使用 Intent 將此操作與 startActivity() 結合使用。
ACTION_SEND
這也稱爲“共享”Intent。如果您擁有一些用戶可通過其他應用(例如,電子郵件應用或社交共享應用)共享的數據,則應使用 Intent 將此操作與 startActivity() 結合使用。
有關更多定義通用操作的常量,請參閱 Intent 類參考文檔。 其他操作在 Android 框架中的其他位置定義。例如,對於在系統的設置應用中打開特定屏幕的操作,將在 Settings 中定義。

您可以使用 setAction() 或 Intent 構造函數爲 Intent 指定操作。

如果定義自己的操作,請確保將應用的軟件包名稱作爲前綴。 例如:

static final String ACTION_TIMETRAVEL = “com.example.action.TIMETRAVEL”;
數據
引用待操作數據和/或該數據 MIME 類型的 URI(Uri 對象)。提供的數據類型通常由 Intent 的操作決定。例如,如果操作是 ACTION_EDIT,則數據應包含待編輯文檔的 URI。
創建 Intent 時,除了指定 URI 以外,指定數據類型(其 MIME 類型)往往也很重要。例如,能夠顯示圖像的 Activity 可能無法播放音頻文件,即便 URI 格式十分類似時也是如此。因此,指定數據的 MIME 類型有助於 Android 系統找到接收 Intent 的最佳組件。但有時,MIME 類型可以從 URI 中推斷得出,特別當數據是 content: URI 時尤其如此。這表明數據位於設備中,且由 ContentProvider 控制,這使得數據 MIME 類型對系統可見。

要僅設置數據 URI,請調用 setData()。 要僅設置 MIME 類型,請調用 setType()。如有必要,您可以使用 setDataAndType() 同時顯式設置二者。

注意:若要同時設置 URI 和 MIME 類型,請勿調用 setData() 和 setType(),因爲它們會互相抵消彼此的值。請始終使用 setDataAndType() 同時設置 URI 和 MIME 類型。

類別
一個包含應處理 Intent 組件類型的附加信息的字符串。 您可以將任意數量的類別描述放入一個 Intent 中,但大多數 Intent 均不需要類別。 以下是一些常見類別:
CATEGORY_BROWSABLE
目標 Activity 允許本身通過網絡瀏覽器啓動,以顯示鏈接引用的數據,如圖像或電子郵件。
CATEGORY_LAUNCHER
該 Activity 是任務的初始 Activity,在系統的應用啓動器中列出。
有關類別的完整列表,請參閱 Intent 類描述。

您可以使用 addCategory() 指定類別。

以上列出的這些屬性(組件名稱、操作、數據和類別)表示 Intent 的既定特徵。 通過讀取這些屬性,Android 系統能夠解析應當啓動哪個應用組件。

但是,Intent 也有可能會一些攜帶不影響其如何解析爲應用組件的信息。 Intent 還可以提供:

Extra
攜帶完成請求操作所需的附加信息的鍵值對。正如某些操作使用特定類型的數據 URI 一樣,有些操作也使用特定的 extra。
您可以使用各種 putExtra() 方法添加 extra 數據,每種方法均接受兩個參數:鍵名和值。您還可以創建一個包含所有 extra 數據的 Bundle 對象,然後使用 putExtras() 將Bundle 插入 Intent 中。

例如,使用 ACTION_SEND 創建用於發送電子郵件的 Intent 時,可以使用 EXTRA_EMAIL 鍵指定“目標”收件人,並使用 EXTRA_SUBJECT 鍵指定“主題”。

Intent 類將爲標準化的數據類型指定多個 EXTRA_* 常量。如需聲明自己的 extra 鍵(對於應用接收的 Intent),請確保將應用的軟件包名稱作爲前綴。 例如:

static final String EXTRA_GIGAWATTS = “com.example.EXTRA_GIGAWATTS”;
標誌
在 Intent 類中定義的、充當 Intent 元數據的標誌。 標誌可以指示 Android 系統如何啓動 Activity(例如,Activity 應屬於哪個任務),以及啓動之後如何處理(例如,它是否屬於最近的 Activity 列表)。

顯式 Intent

顯式 Intent 是指用於啓動某個特定應用組件(例如,應用中的某個特定 Activity 或服務)的 Intent。 要創建顯式 Intent,請爲 Intent 對象定義組件名稱 — Intent 的所有其他屬性均爲可選屬性。
比如啓動一個Activity:
Intent intent = new Intent(Context,要跳轉到的Activity);
startActivity(intent);

隱式 Intent

隱式 Intent 指定能夠在可以執行相應操作的設備上調用任何應用的操作。 如果您的應用無法執行該操作而其他應用可以,且您希望用戶選取要使用的應用,則使用隱式 Intent 非常有用。
例如,如果您希望用戶與他人共享您的內容,請使用 ACTION_SEND 操作創建 Intent,並添加指定共享內容的 extra。 使用該 Intent 調用 startActivity() 時,用戶可以選取共享內容所使用的應用。

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

// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

注:在這種情況下,系統並沒有使用 URI,但已聲明 Intent 的數據類型,用於指定 extra 攜帶的內容。

調用 startActivity() 時,系統將檢查已安裝的所有應用,確定哪些應用能夠處理這種 Intent(即:含 ACTION_SEND 操作並攜帶“text/plain”數據的 Intent )。 如果只有一個應用能夠處理,則該應用將立即打開併爲其提供 Intent。 如果多個 Activity 接受 Intent,則系統將顯示一個對話框,使用戶能夠選取要使用的應用。

強制使用應用選擇器

如果有多個應用響應隱式 Intent,則用戶可以選擇要使用的應用,並將其設置爲該操作的默認選項。 如果用戶可能希望今後一直使用相同的應用執行某項操作(例如,打開網頁時,用戶往往傾向於僅使用一種網絡瀏覽器),則這一點十分有用。

但是,如果多個應用可以響應 Intent,且用戶可能希望每次使用不同的應用,則應採用顯式方式顯示選擇器對話框。 選擇器對話框每次都會要求用戶選擇用於操作的應用(用戶無法爲該操作選擇默認應用)。 例如,當應用使用 ACTION_SEND 操作執行“共享”時,用戶根據目前的狀況可能需要使用另一不同的應用,因此應當始終使用選擇器對話框,如圖 中所示。
這裏寫圖片描述

要顯示選擇器,請使用 createChooser() 創建 Intent,並將其傳遞給 startActivity()。例如:

Intent sendIntent = new Intent(Intent.ACTION_SEND);
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);

// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

這將顯示一個對話框,其中有響應傳遞給 createChooser() 方法的 Intent 的應用列表,並且將提供的文本用作對話框標題。

接收隱式 Intent

要公佈應用可以接收哪些隱式 Intent,請在清單文件中使用 元素爲每個應用組件聲明一個或多個 Intent 過濾器。每個 Intent 過濾器均根據 Intent 的操作、數據和類別指定自身接受的 Intent 類型。 僅當隱式 Intent 可以通過 Intent 過濾器之一傳遞時,系統纔會將該 Intent 傳遞給應用組件。

注:顯式 Intent 始終會傳遞給其目標,無論組件聲明的 Intent 過濾器如何均是如此。

應用組件應當爲自身可執行的每個獨特作業聲明單獨的過濾器。例如,圖像庫應用中的一個 Activity 可能會有兩個過濾器,分別用於查看圖像和編輯圖像。 當 Activity 啓動時,它將檢查 Intent 並根據 Intent 中的信息決定具體的行爲(例如,是否顯示編輯器控件)。

每個 Intent 過濾器均由應用清單文件中的 元素定義,並嵌套在相應的應用組件(例如, 元素)中。 在 內部,您可以使用以下三個元素中的一個或多個指定要接受的 Intent 類型:


在 name 屬性中,聲明接受的 Intent 操作。該值必須是操作的文本字符串值,而不是類常量。

使用一個或多個指定數據 URI 各個方面(scheme、host、port、path 等)和 MIME 類型的屬性,聲明接受的數據類型。

在 name 屬性中,聲明接受的 Intent 類別。該值必須是操作的文本字符串值,而不是類常量。
注:爲了接收隱式 Intent,必須將 CATEGORY_DEFAULT 類別包括在 Intent 過濾器中。 方法 startActivity() 和 startActivityForResult() 將按照已申明 CATEGORY_DEFAULT 類別的方式處理所有 Intent。 如果未在 Intent 過濾器中聲明此類別,則隱式 Intent 不會解析爲您的 Activity。

例如,以下是一個使用包含 Intent 過濾器的 Activity 聲明,當數據類型爲文本時,系統將接收 ACTION_SEND Intent :

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

您可以創建一個包括多個 、 或 實例的過濾器。創建時,僅需確定組件能夠處理這些過濾器元素的任何及所有組合即可。

如需僅以操作、數據和類別類型的特定組合來處理多種 Intent,則需創建多個 Intent 過濾器。
系統通過將 Intent 與所有這三個元素進行比較,根據過濾器測試隱式 Intent。 隱式 Intent 若要傳遞給組件,必須通過所有這三項測試。如果 Intent 甚至無法匹配其中任何一項測試,則 Android 系統不會將其傳遞給組件。 但是,由於一個組件可能有多個 Intent 過濾器,因此未能通過某一組件過濾器的 Intent 可能會通過另一過濾器。如需瞭解有關係統如何解析 Intent 的詳細信息,請參閱下文的 Intent 解析部分。

注意:爲了避免無意中運行不同應用的 Service,請始終使用顯式 Intent 啓動您自己的服務,且不必爲該服務聲明 Intent 過濾器。

注:對於所有 Activity,您必須在清單文件中聲明 Intent 過濾器。但是,廣播接收器的過濾器可以通過調用 registerReceiver() 動態註冊。 稍後,您可以使用 unregisterReceiver() 註銷該接收器。這樣一來,應用便可僅在應用運行時的某一指定時間段內偵聽特定的廣播。

限制對組件的訪問
使用 Intent 過濾器時,無法安全地防止其他應用啓動組件。 儘管 Intent 過濾器將組件限制爲僅響應特定類型的隱式 Intent,但如果開發者確定您的組件名稱,則其他應用有可能通過使用顯式 Intent 啓動您的應用組件。如果必須確保只有您自己的應用才能啓動您的某一組件,請針對該組件將 exported 屬性設置爲 “false”。

過濾器使用

爲了更好地瞭解一些 Intent 過濾器的行爲,我們一起來看看從社交共享應用的清單文件中截取的以下片段。

<activity android:name="MainActivity">
    <!-- This activity is the main entry, should appear in app launcher -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity">
    <!-- This activity handles "SEND" actions with text data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="application/vnd.google.panorama360+jpg"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
</activity>

第一個 Activity MainActivity 是應用的主要入口點。當用戶最初使用啓動器圖標啓動應用時,該 Activity 將打開:

ACTION_MAIN 操作指示這是主要入口點,且不要求輸入任何 Intent 數據。
CATEGORY_LAUNCHER 類別指示此 Activity 的圖標應放入系統的應用啓動器。 如果 元素未使用 icon 指定圖標,則系統將使用 元素中的圖標。
這兩個元素必須配對使用,Activity 纔會顯示在應用啓動器中。

第二個 Activity ShareActivity 旨在便於共享文本和媒體內容。 儘管用戶可以通過從 MainActivity 導航進入此 Activity,但也可以從發出隱式 Intent(與兩個 Intent 過濾器之一匹配)的另一應用中直接進入 ShareActivity。

注:MIME 類型 application/vnd.google.panorama360+jpg 是一個指定全景照片的特殊數據類型,您可以使用 Google panorama API 對其進行處理。

使用待定 Intent

PendingIntent 對象是 Intent 對象的包裝器。PendingIntent 的主要目的是授權外部應用使用包含的 Intent,就像是它從您應用本身的進程中執行的一樣。

待定 Intent 的主要用例包括:

聲明用戶使用您的通知執行操作時所要執行的 Intent(Android 系統的 NotificationManager 執行 Intent)。
聲明用戶使用您的 應用小部件執行操作時要執行的 Intent(主屏幕應用執行 Intent)。
聲明未來某一特定時間要執行的 Intent(Android 系統的 AlarmManager 執行 Intent)。
由於每個 Intent 對象均設計爲由特定類型的應用組件(Activity、Service 或 BroadcastReceiver)進行處理,因此還必須基於相同的考慮因素創建 PendingIntent。使用待定 Intent 時,應用不會使用調用(如 startActivity())執行該 Intent。相反,通過調用相應的創建器方法創建 PendingIntent 時,您必須聲明所需的組件類型:

PendingIntent.getActivity(),適用於啓動 Activity 的 Intent。
PendingIntent.getService(),適用於啓動 Service 的 Intent。
PendingIntent.getBroadcast(),適用於啓動 BroadcastReceiver 的 Intent。
除非您的應用正在從其他應用中接收待定 Intent,否則上述用於創建 PendingIntent 的方法可能是您所需的唯一 PendingIntent 方法。

每種方法均會提取當前的應用 Context、您要包裝的 Intent 以及一個或多個指定應如何使用該 Intent 的標誌(例如,是否可以多次使用該 Intent)。

Intent 解析

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

Intent 操作
Intent 數據(URI 和數據類型)
Intent 類別
下文根據如何在應用的清單文件中聲明 Intent 過濾器,描述 Intent 如何與相應的組件匹配。

操作測試
要指定接受的 Intent 操作,Intent 過濾器既可以不聲明任何 元素,也可以聲明多個此類元素。例如:

<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>

要通過此過濾器,您在 Intent 中指定的操作必須與過濾器中列出的某一操作匹配。

如果該過濾器未列出任何操作,則 Intent 沒有任何匹配項,因此所有 Intent 均無法通過測試。 但是,如果 Intent 未指定操作,則會通過測試(只要過濾器至少包含一個操作)。

類別測試
要指定接受的 Intent 類別, Intent 過濾器既可以不聲明任何 元素,也可以聲明多個此類元素。 例如:





若要使 Intent 通過類別測試,則 Intent 中的每個類別均必須與過濾器中的類別匹配。反之則未必然,Intent 過濾器聲明的類別可以超出 Intent 中指定的數量,且 Intent 仍會通過測試。 因此,不含類別的 Intent 應當始終會通過此測試,無論過濾器中聲明何種類別均是如此。

注:Android 會自動將 CATEGORY_DEFAULT 類別應用於傳遞給 startActivity() 和 startActivityForResult() 的所有隱式 Intent。因此,如需 Activity 接收隱式 Intent,則必須將 “android.intent.category.DEFAULT” 的類別包括在其 Intent 過濾器中(如上文的 示例所示)。

數據測試
要指定接受的 Intent 數據, Intent 過濾器既可以不聲明任何 元素,也可以聲明多個此類元素。 例如:

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

每個 元素均可指定 URI 結構和數據類型(MIME 媒體類型)。 URI 的每個部分均包含單獨的 scheme、host、port 和 path 屬性:

://:/

例如:

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

在此 URI 中,架構是 content,主機是 com.example.project,端口是 200,路徑是 folder/subfolder/etc。

在 元素中,上述每個屬性均爲可選,但存在線性依賴關係:

如果未指定架構,則會忽略主機。
如果未指定主機,則會忽略端口。
如果未指定架構和主機,則會忽略路徑。
將 Intent 中的 URI 與過濾器中的 URI 規範進行比較時,它僅與過濾器中包含的部分 URI 進行比較。 例如:

如果過濾器僅指定架構,則具有該架構的所有 URI 均與該過濾器匹配。
如果過濾器指定架構和權限,但未指定路徑,則具有相同架構和權限的所有 URI 都會通過過濾器,無論其路徑如何均是如此。
如果過濾器指定架構、權限和路徑,則僅具有相同架構、權限和路徑的 URI 纔會通過過濾器。
注:路徑規範可以包含星號通配符 (*),因此僅需部分匹配路徑名即可。

數據測試會將 Intent 中的 URI 和 MIME 類型與過濾器中指定的 URI 和 MIME 類型進行比較。 規則如下:

A,僅當過濾器未指定任何 URI 或 MIME 類型時,不含 URI 和 MIME 類型的 Intent 纔會通過測試。
B,對於包含 URI 但不含 MIME 類型(既未顯式聲明,也無法通過 URI 推斷得出)的 Intent,僅當其 URI 與過濾器的 URI 格式匹配、且過濾器同樣未指定 MIME 類型時,纔會通過測試。
C,僅當過濾器列出相同的 MIME 類型且未指定 URI 格式時,包含 MIME 類型、但不含 URI 的 Intent 纔會通過測試。
D,僅當 MIME 類型與過濾器中列出的類型匹配時,同時包含 URI 類型和 MIME 類型(通過顯式聲明,或可以通過 URI 推斷得出)的 Intent 纔會通過測試的 MIME 類型部分。 如果 Intent 的 URI 與過濾器中的 URI 匹配,或者如果 Intent 具有 content: 或 file: URI 且過濾器未指定 URI,則 Intent 會通過測試的 URI 部分。 換言之,如果過濾器只是列出 MIME 類型,則假定組件支持 content: 和 file: 數據。
最後一條規則,即規則 (d),反映了期望組件能夠從文件中或內容提供程序獲得本地數據。因此,其過濾器可以僅列出數據類型,而不必顯式命名 content: 和 file: 架構。這是一個典型的案例。 例如,下文中的 元素向 Android 指出,組件可從內容提供商處獲得並顯示圖像數據:

<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>
``

由於大部分可用數據均由內容提供商分發,因此指定數據類型(而非 URI)的過濾器也許最爲常見。

另一常見的配置是具有架構和數據類型的過濾器。例如,下文中的 <data> 元素向 Android 指出,組件可從網絡中檢索視頻數據以執行操作:


<intent-filter>
    <data android:scheme="http" android:type="video/*" />
    ...
</intent-filter>

Intent 匹配

通過 Intent 過濾器匹配 Intent,這不僅有助於發現要激活的目標組件,還有助於發現設備上組件集的相關信息。 例如,主頁應用通過使用指定 ACTION_MAIN 操作和 CATEGORY_LAUNCHER 類別的 Intent 過濾器查找所有 Activity,以此填充應用啓動器。

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

摘自:https://developer.android.google.cn/guide/components/intents-filters.html#PendingIntent

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章