Intent
是可用來要求動作的訊息物件
從其他應用程式元件擷取物件
雖然意圖可透過多種方式促進元件之間的通訊,但仍有三種
基本用途
- 啟動活動
Activity
代表應用程式中的單一畫面。你可以發起新的Activity
的例項,方法是傳遞Intent
至startActivity()
。Intent
描述了啟動並攜帶任何必要資料的活動。如果您想在活動完成後收到結果, 呼叫
startActivityForResult()
。您的活動會收到結果 在活動的onActivityResult()
回呼中,做為個別Intent
物件。 詳情請參閱「活動」指南。 - 啟動服務
Service
是會在背景執行作業的元件 不必使用使用者介面在 Android 5.0 (API 級別 21) 以上版本中,您可以啟動服務 只在JobScheduler
。如要進一步瞭解 關於「JobScheduler
」,請參閱API-reference documentation
。如果是 Android 5.0 (API 級別 21) 以下版本,則可以使用
Service
類別的方法。您可以啟動服務 執行一次性作業 (例如下載檔案) 方法是傳遞Intent
至startService()
。Intent
描述服務以啟動並傳送任何必要資料。如果這項服務是以用戶端伺服器介面設計而成,您即可繫結至該服務 將
Intent
傳遞至bindService()
,藉此從另一個元件中取出。詳情請參閱服務指南。 - 播送播送內容
廣播是所有應用程式可接收的訊息。這套系統提供多項 廣播訊息,例如系統啟動或裝置開始充電時。 您可以藉由傳遞
Intent
,將廣播訊息傳遞到其他應用程式 到sendBroadcast()
或sendOrderedBroadcast()
。
本頁面其餘部分將說明意圖的運作方式及使用方法。 如需相關資訊,請參閱 與其他應用程式互動 和分享內容。
意圖類型
意圖有兩種類型:
- 明確意圖:指定完整的
ComponentName
,指定應用程式滿足意圖的元件。您 通常會使用明確意圖,在 應用程式,因為您知道要啟動的活動或服務的類別名稱。適用對象 舉例來說,您可能會為了回應使用者操作,或在應用程式內啟動新活動 可在背景下載檔案的服務。 - 「隱式意圖」不會指特定元件,而是宣告一般動作 執行,可讓其他應用程式的元件處理舉例來說 顯示地圖上的位置,您可以使用隱含意圖,要求另一個 應用程式會在地圖上顯示特定位置。
圖 1 說明啟動活動時如何使用意圖。當
Intent
物件明確命名特定活動元件,系統
就會立即啟動該元件
![](https://developer.android.com/static/images/components/intent-filters_2x.png?authuser=0000&hl=zh-tw)
圖 1. 隱含意圖
以便開始另一項活動:[1] 活動 A 會建立
包含動作說明的 Intent
,並傳遞至 startActivity()
。[2] Android 系統搜尋所有內容
。找到相符內容時,系統會 [3] 由系統判定
叫用其 onCreate()
方法並傳遞 Intent
,啟動相符的活動 (Activity B)。
使用隱含意圖時,Android 系統會尋找適當的元件來啟動
,比較意圖內容與其他應用程式資訊清單檔案中宣告的意圖篩選器
裝置。如果意圖符合意圖篩選器,系統會啟動該元件並提交要求
Intent
物件。如果相容的多個意圖篩選器,系統會
會顯示對話方塊,方便使用者挑選要使用的應用程式。
意圖篩選器是應用程式資訊清單檔案中的運算式, 會指定元件的意圖類型 。例如,為活動宣告意圖篩選器後 您可讓其他應用程式直接以某種特定意圖啟動您的活動。 同樣地,如果您「不」為活動宣告任何意圖篩選器,系統就會啟動 只用於明確意圖
注意:為確保應用程式安全無虞,請務必一律
使用
意圖 (Service
),但不需要
為服務宣告意圖篩選器。使用隱含意圖啟動服務是
可能會產生安全性危害,因為您無法確定哪個服務會回應意圖
導致使用者看不到哪個服務啟動了。從 Android 5.0 (API 級別 21) 開始,系統
若呼叫 bindService()
,就會擲回例外狀況
針對隱含意圖
建立意圖
Intent
物件包含 Android 系統使用的資訊
,決定要啟動的元件 (例如確切的元件名稱或元件)
用來接收意圖的類別),再加上收件者元件用於
以便正確執行操作,例如要採取的動作和套用的資料。
Intent
中包含的主要資訊如下:
- 元件名稱
- 要啟動的元件名稱。
這不是必要步驟,但這是建立意圖的關鍵資訊 「顯式」:表示意圖只應傳送至應用程式元件 由元件名稱定義如果沒有元件名稱,意圖會是「隱含」, 系統會根據其他意圖資訊,判斷哪個元件應接收意圖 (例如下述動作、資料和類別)。如果要在 元件中,您應該指定元件名稱。
注意:啟動
Service
時, 請務必指定元件名稱。否則,您就無法確定哪個服務 會回應意圖,而且使用者無法查看哪個服務會啟動。Intent
的這個欄位是ComponentName
物件,您可以使用完整的 目標元件的合格類別名稱,包括應用程式的套件名稱,例如com.example.ExampleActivity
。您可以透過setComponent()
、setClass()
、setClassName()
、 或Intent
建構函式。 - 動態
- 用來指定要執行的一般動作 (例如「view」或「pick」) 的字串。
如為廣播意圖,這是指系統回報的動作。 動作主要會決定其餘意圖的結構 (尤其是 資料和額外項目內含的資訊。
您可以指定自己的動作,供應用程式中的意圖使用 (或供其他意圖使用) 來叫用應用程式元件),但您通常會指定動作常數 由
Intent
類別或其他架構類別定義以下是一些 啟動活動的常見動作:ACTION_VIEW
- 當您擁有一些資訊,且該意圖使用
startActivity()
時,請在意圖中使用此動作 可以向使用者顯示活動,例如要在圖片庫應用程式查看的相片,或是允許 在地圖應用程式中查看。 ACTION_SEND
- 也稱為「共用」意圖,如果您有足夠的資料可供使用者運用,應該在搭配
startActivity()
的意圖中使用此意圖。 透過其他應用程式分享,例如電子郵件應用程式或社群媒體分享應用程式。
詳情請參閱
Intent
類別參考資料 定義一般動作的常數。其他動作的定義如下 安裝在 Android 架構中的其他位置,例如使用Settings
執行動作 在系統「設定」應用程式中開啟特定畫面。您可以使用
setAction()
或Intent
建構函式為意圖指定動作。如果自行定義動作,請務必加入應用程式的套件名稱 做為前置字串,如以下範例所示:
Kotlin
const val ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL"
Java
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
- 資料
- 參照資料的 URI (
Uri
物件) 處理相關事宜,和/或 該資料的 MIME 類型。提供的資料類型通常會取決於意圖的動作。適用對象 舉例來說,如果動作是ACTION_EDIT
,資料就應包含 要編輯的文件 URI。建立意圖時 除了 URI 之外,您也必須指定資料類型 (其 MIME 類型)。 舉例來說,能夠顯示圖片的活動可能無法顯示 播放音訊檔案,不過 URI 格式可能很類似。 指定資料的 MIME 類型,可幫助 Android 系統會尋找最佳的元件來接收意圖 不過,有時可以從 URI 推斷 MIME 類型,尤其是當資料是
content:
URI。content:
URI 表示資料位於裝置上 並由不同叢集ContentProvider
,系統會允許系統顯示資料 MIME 類型。如果只要設定資料 URI,請呼叫
setData()
。 如果只要設定 MIME 類型,請呼叫setType()
。如有需要, 可以使用setDataAndType()
明確設定這兩項功能。注意:如要同時設定 URI 和 MIME 類型, 「不要」呼叫
setData()
和setType()
會分別使其他值的值空值。 一律使用setDataAndType()
來設定兩者 URI 和 MIME 類型。 - 類別
- 包含特定元件類型額外資訊的字串
系統應能處理意圖類別說明的數量不限
但是大多數意圖都不需要類別
以下列舉幾個常見的類別:
CATEGORY_BROWSABLE
- 網路瀏覽器可自行啟動目標活動來顯示資料 透過連結 (例如圖片或電子郵件) 參照。
CATEGORY_LAUNCHER
- 此活動是任務的初始活動,會列於 系統的應用程式啟動器
如需完整清單,請參閱
Intent
類別說明 類別您可以使用
addCategory()
指定類別。
上述屬性 (元件名稱、動作、資料和類別) 代表 定義意圖的特徵透過讀取這些屬性,Android 系統 可以解析出應啟動哪個應用程式元件。然而,意圖可以是 不影響其他資料 如何解析為應用程式元件意圖也可以提供以下資訊:
- 額外內容
- 包含要達成的額外資訊的鍵/值組合
要求的動作
就像某些動作會使用特定種類的資料 URI 一樣,有些動作也會使用特定的額外項目。
您可以透過各種
putExtra()
方法新增額外資料。 每一個都接受兩個參數:鍵名和值 您也可以使用所有額外資料建立Bundle
物件,然後插入 含有putExtras()
的Intent
中的Bundle
。例如,建立意圖以內含
ACTION_SEND
可讓您將 to 收件者指定為EXTRA_EMAIL
鍵,然後將主旨指定為EXTRA_SUBJECT
鍵。Intent
類別指定多個EXTRA_*
常數 標準化資料類型如果需要宣告自己的額外鍵 (適用於 應用程式收到更新時,請務必加入應用程式的套件名稱 做為前置字串,如以下範例所示:Kotlin
const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
Java
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
注意:請勿使用
Parcelable
或 傳送預期中的意圖時,系統會處理Serializable
的資料 即可接收其他應用程式的通知。如果是應用程式 嘗試存取Bundle
物件中的資料,但不會嘗試存取 可存取 Parceled 或序列化類別,則會引發RuntimeException
。 - 標記
- 旗標是在
Intent
類別中定義,該類別的功能是 意圖。這些標記可能會指示 Android 系統如何啟動活動 (例如 工作 活動應屬於 ) 推出後的方法,以及該功能推出後應如何處理 (例如是否列於近期清單內) 活動)。詳情請參閱
setFlags()
方法。
明確意圖範例
明確意圖,是用來啟動特定應用程式元件的應用程式,例如
應用程式中的特定活動或服務。如要建立明確意圖,請定義
Intent
物件的元件名稱—
以及選用其他意圖屬性
舉例來說,假設您在應用程式中建構了名為 DownloadService
的服務,
這個程式的用途是從網路下載檔案,您可以從下列程式碼開始著手:
Kotlin
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" val downloadIntent = Intent(this, DownloadService::class.java).apply { data =Uri.parse
(fileUrl) } startService(downloadIntent)
Java
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" Intent downloadIntent = new Intent(this, DownloadService.class); downloadIntent.setData(Uri.parse
(fileUrl)); startService(downloadIntent);
Intent(Context, Class)
建構函式會提供應用程式 Context
和
元件為 Class
物件因此
此意圖會明確啟動應用程式中的 DownloadService
類別。
如要進一步瞭解如何建構及啟動服務,請參閱 服務指南。
隱含意圖範例
隱含意圖會指定一項動作,能在裝置上叫用任何應用程式 來執行動作如果應用程式無法執行 但其他應用程式或許會讓您選擇想用的應用程式。
例如,如果您要讓使用者與其他人分享自己的內容
建立意圖
搭配「ACTION_SEND
」動作
並新增其他項目來指定要共用的內容撥打電話時
startActivity()
和該意圖後,使用者就能
選擇要用來分享內容的應用程式。
Kotlin
// Create the text message with a string. val sendIntent = Intent().apply { action = Intent.ACTION_SEND putExtra(Intent.EXTRA_TEXT, textMessage) type = "text/plain" } // Try to invoke the intent. try { startActivity(sendIntent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
// 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"); // Try to invoke the intent. try { startActivity(sendIntent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
呼叫 startActivity()
時,系統會
檢查所有已安裝的應用程式,判斷哪些應用程式能夠處理這類意圖 (
意圖為 ACTION_SEND
動作且包含「text/plain」的意圖
資料)。如果只有一個應用程式可處理這個程式碼,該應用程式會立即開啟,並給予
意圖。如果沒有其他應用程式能夠處理,則您的應用程式可擷取
ActivityNotFoundException
敬上
。如果有多個活動接受意圖,系統會
會顯示對話方塊 (如圖 2 所示),因此使用者可以挑選要使用的應用程式。
指南也提供如何啟動其他應用程式的詳細資訊 關於將使用者引導至 其他應用程式。
![](https://developer.android.com/static/images/training/basics/intent-chooser.png?authuser=0000&hl=zh-tw)
圖 2. 選擇工具對話方塊。
強制使用應用程式選擇工具
如有多個應用程式回應您的隱含意圖, 使用者可以選擇要使用的應用程式,並將該應用程式設為預設選項 動作。當使用者要執行某個動作時,可以選取預設值 可能每次都使用同一個應用程式,例如開啟網頁時 通常偏好只使用單一網路瀏覽器)。
不過,如果多個應用程式可以回應意圖,則使用者可能會想使用不同的
應用程式,都應明確顯示選擇器對話方塊。選擇器對話方塊會詢問
使用者選取要用於該動作的應用程式 (使用者無法選取
該動作)。舉例來說,如果應用程式會執行「分享」若是 ACTION_SEND
動作,則使用者可能會想根據不同條件使用其他應用程式共用內容
建議您一律使用選擇器對話方塊,如圖 2 所示。
如要顯示選擇工具,請使用 createChooser()
建立 Intent
,並傳送至 startActivity()
,如以下範例所示。
本範例顯示的對話方塊含有應用程式清單,這些應用程式會回應傳遞至 createChooser()
方法的意圖,並使用提供的文字做為
對話方塊標題。
Kotlin
val sendIntent = Intent(Intent.ACTION_SEND) ... // Always use string resources for UI text. // This says something like "Share this photo with" val title: String = resources.getString(R.string.chooser_title) // Create intent to show the chooser dialog val chooser: Intent = Intent.createChooser(sendIntent, title) // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(packageManager) != null) { startActivity(chooser) }
Java
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); }
偵測不安全的意圖啟動作業
應用程式可能會啟動意圖,以在應用程式內的各個元件之間瀏覽, 或代表其他應用程式執行動作為了提昇平台安全性 Android 12 (API 級別 31) 以上版本提供偵錯功能,用於發出警告 應用程式會執行不安全的意圖啟動作業。舉例來說,您的應用程式 執行不安全的巢狀意圖 (也就是傳遞的意圖) 時 做為另一個意圖中的額外項目
如果應用程式同時執行下列這兩項動作,系統偵測到不安全 意圖啟動,以及 StrictMode 違規 發生:
- 應用程式將巢狀意圖從已傳遞意圖的額外項目中拆解出來。
- 您的應用程式立即啟動一個應用程式
特定巢狀意圖的元件
例如將意圖傳遞至
startActivity()
、startService()
, 或bindService()
。
如要進一步瞭解如何找出這種情況並修改應用程式, 閱讀有關 Android 巢狀結構的網誌文章 意圖 在 Medium 上
檢查是否有不安全的意圖啟動作業
如要檢查應用程式中的不安全意圖啟動作業,請呼叫
detectUnsafeIntentLaunch()
敬上
設定 VmPolicy
時,如以下程式碼片段所示。如果
應用程式偵測到 StrictMode 違規事件,建議你停止執行應用程式
保護潛在機密資訊
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()) }
Java
protected void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()); }
以更負責任的方式使用意圖
為了盡量降低意圖啟動不安全意圖並違反 StrictMode 違規的機率 請遵循以下最佳做法
僅複製意圖中必要額外項目,然後執行任何必要操作
衛生及驗證。應用程式可能會將額外功能從一個意圖複製到
用於啟動新元件的其他意圖這種情況會發生在
應用程式呼叫
putExtras(Intent)
敬上
或
putExtras(Bundle)
。
如果您的應用程式會執行其中一項作業,請僅複製
接收相應的元件如果其他意圖 (收到副本)
啟動未啟動的元件
exported、清理及
先驗證額外項目再將其複製到啟動
元件。
避免在非必要的情況下匯出應用程式的元件。舉例來說,如果您在
打算使用內部巢狀意圖啟動應用程式元件,請設定
將元件的 android:exported
屬性設為 false
。
使用 PendingIntent
,而不是
巢狀結構意圖。這樣一來,當另一個應用程式解開自身的 PendingIntent
時
包含 Intent
,其他應用程式則可使用 PendingIntent
識別應用程式的身分這項設定可讓其他應用程式安全地啟動
應用程式中的任何元件,包括未匯出的元件。
圖 2 中的圖表顯示系統如何傳遞您 (用戶端) 的控制權 應用程式,然後再返回您的應用程式:
- 應用程式建立一個意圖,在另一個應用程式中叫用活動。在特定時間範圍內
您需要新增
PendingIntent
物件做為額外項目這個待處理意圖 在應用程式中叫用元件;系統不會匯出這個元件 - 收到應用程式的意圖後,其他應用程式會擷取巢狀結構
PendingIntent
物件。 - 另一個應用程式對
PendingIntent
物件叫用send()
方法。 - 將控制權移回應用程式後,系統會叫用待處理 修改應用程式意圖的意圖
圖 2.使用巢狀待處理結構時,應用程式內通訊的圖表 意圖。
接收隱含意圖
如要宣傳應用程式可接收的隱含意圖,請宣告一或多個意圖篩選器:
每個應用程式元件,各有一個 <intent-filter>
加入資訊清單檔案中的元素。
每個意圖篩選器都會根據意圖的動作指定所接受的意圖類型。
資料和類別只有在下列情況中,系統才會為應用程式元件提供隱含意圖
意圖通過其中一個意圖篩選器
注意:明確意圖一律會傳送至其目標。 無論元件宣告的任何意圖篩選器皆是一樣的
應用程式元件應為每個可執行的不重複工作宣告不同的篩選器。
舉例來說,某個圖片庫應用程式中的一項活動可以使用以下兩個篩選器:一個篩選器
「查看圖片」和「編輯圖片」篩選器活動開始時
程式碼會檢查 Intent
,並根據資訊決定處置方式
在 Intent
中 (例如不顯示編輯器控制項)。
每個意圖篩選器都是由 <intent-filter>
定義
元素,以巢狀結構嵌入對應的應用程式元件中 (例如
為 <activity>
元素)。
在每個包含 <intent-filter>
元素的應用程式元件中,
明確設定一個
android:exported
。
這個屬性指出其他應用程式是否能存取該應用程式元件。某些
例如,如果活動的意圖篩選器包含
LAUNCHER
敬上
最好將這項屬性設為 true
否則
建議您將這項屬性設為 false
。
警告:如果活動、服務或廣播訊息
應用程式中的接收器使用意圖篩選器,且並未明確設定該值
如果是 android:exported
,您無法在以下裝置上安裝應用程式:
搭載 Android 12 以上版本。
在 <intent-filter>
中,
您可以使用一或多個方式,指定要接受的意圖類型
以上三個要素:
<action>
- 在
name
屬性中宣告已接受的意圖動作。這個鍵 必須是動作的常值字串值,而非類別常數。 <data>
- 使用一或多個指定各種屬性的屬性,宣告可接受的資料類型
資料 URI 方面 (
scheme
、host
、port
path
) 和 MIME 類型。 <category>
- 在
name
屬性中宣告可接受的意圖類別。這個鍵 必須是動作的常值字串值,而非類別常數。注意:如要接收隱含意圖,您必須 必須包含
CATEGORY_DEFAULT
類別。方法 「startActivity()
」和startActivityForResult()
會將所有意圖視為 就像他們宣告CATEGORY_DEFAULT
類別一樣 如果您未在意圖篩選器中宣告這個類別,系統就不會將任何隱含意圖解析為 您的活動。
舉例來說,以下活動宣告內含意圖篩選器接收
ACTION_SEND
意圖 (資料類型為文字):
<activity android:name="ShareActivity" android:exported="false"> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity>
您可以建立包含多個項目
<action>
、
<data>
,或
<category>
。
如果這樣做,您就必須確定該元件能夠處理任何及所有
這些篩選器元素的組合
當您想處理多種類型的意圖,但只在特定組合的 動作、資料和類別類型,然後建立多個意圖篩選器。
將隱含意圖與篩選器的意圖進行比較, 三個元素意圖必須通過全部三項測試,才能傳送至元件。 如果應用程式連一個都無法比對,Android 系統就不會將意圖傳遞給 元件。然而,由於一個元件可能包含多個意圖篩選器, 未通過元件的任一篩選器,就有可能通過其他篩選器篩選。 如要進一步瞭解系統解析意圖的方式,請參閱下一節 意圖解析。
注意: 使用意圖篩選器並非防止其他應用程式啟動的安全方法
您的元件雖然意圖篩選器會限制元件只能回應
有些類型的隱含意圖,其他應用程式可能會啟動您的應用程式元件
如果開發人員決定您的元件名稱,就必須使用明確意圖。
如果「只有您自己的應用程式」能夠啟動其中一個元件,
未在資訊清單中宣告意圖篩選器。請改為將
exported
屬性
將元件設為 "false"
同樣地,為了避免不慎
執行其他應用程式的
Service
,一律使用明確意圖來啟動您自己的服務。
注意:
對於所有活動,您必須在資訊清單檔案中宣告意圖篩選器。
不過,您可以透過呼叫,以動態方式登錄廣播接收器的篩選器
registerReceiver()
。接著,您可以使用 unregisterReceiver()
取消註冊接收器。這麼做可讓應用程式
只在應用程式指定的時間範圍內收聽特定廣播訊息
正在運作。
篩選器範例
以下舉例說明意圖篩選器的部分行為 改為使用社交分享應用程式的資訊清單檔案:
<activity android:name="MainActivity" android:exported="true"> <!-- 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" android:exported="false"> <!-- 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>
第一個活動 MainActivity
是應用程式的主要進入點,也就是
在使用者初次透過啟動器圖示啟動應用程式時開啟:
ACTION_MAIN
動作 表示這是主要進入點,且不需要任何意圖資料。CATEGORY_LAUNCHER
類別表示該活動的 圖示應放置在系統的應用程式啟動器中。如果<activity>
元素 並未以icon
指定圖示,則系統會使用<application>
的圖示 元素。
這兩項功能必須搭配在一起,活動才會顯示在應用程式啟動器中。
第二項活動 (ShareActivity
) 是用於分享文字和媒體
內容。雖然使用者可能會從「MainActivity
」前往該活動,
使用者也可以在發出隱含要求的其他應用程式中,直接輸入 ShareActivity
符合其中一個意圖篩選器的意圖
注意:MIME 類型
application/vnd.google.panorama360+jpg
是特殊資料類型,用於指定
或全景的相片,你可以透過 Google
全景 API
將意圖與其他應用程式進行比對意圖篩選器
如果其他應用程式指定 Android 13 (API 級別 33) 以上版本,就可以處理
只有在您的意圖與應用程式的
該應用程式的 <intent-filter>
元素。如果系統找不到
因此系統會擲回
ActivityNotFoundException
。
傳送端應用程式必須處理
。
同樣地,如果您將應用程式更新為指定 Android 13 版本,
來自外部應用程式的所有意圖都會傳送至
前提是該意圖與動作和
應用程式所宣告的 <intent-filter>
元素類別。這項行為
無論傳送端應用程式的指定 SDK 版本為何,都會發生這類事件。
在下列情況下,系統不會強制執行意圖比對:
- 在未宣告任何意圖篩選器的元件放送的意圖。
- 來自同一應用程式內的意圖。
- 來自系統的意圖;也就是從
「系統 UID」(uid=1000)。系統應用程式包括
system_server
,以及android:sharedUserId
到android.uid.system
。 - 源自根的意圖。
進一步瞭解意圖比對。
使用待處理意圖
PendingIntent
物件是 Intent
物件的包裝函式。PendingIntent
的主要用途
是將權限授予外國應用程式
使用內含的 Intent
,就像從
應用程式專屬的程序
待處理意圖的主要用途包括:
- 透過通知,宣告當使用者執行動作時將執行的意圖
(Android 系統的
NotificationManager
會執行Intent
)。 - 宣告當使用者透過您的 Google 操作執行動作時將執行的意圖
應用程式小工具
(主畫面應用程式會執行
Intent
)。 - 宣告要在指定未來時間執行的意圖 (Android
系統的
AlarmManager
會執行Intent
)。
就像每個 Intent
物件的設計都是由特定的
應用程式元件的類型 (Activity
、Service
或
是 BroadcastReceiver
),因此也必須是 PendingIntent
都具有相同考量使用待處理意圖時,應用程式
透過 startActivity()
等呼叫執行意圖。相反地,您必須在建立
PendingIntent
,方法是呼叫相應的創作者方法:
PendingIntent.getActivity()
代表 用於啟動Activity
的Intent
。PendingIntent.getService()
代表 用於啟動Service
的Intent
。PendingIntent.getBroadcast()
代表 用於啟動BroadcastReceiver
的Intent
。
除非應用程式從其他應用程式接收待處理意圖,否則:
建立 PendingIntent
的方法可能只有
所需的 PendingIntent
方法。
每個方法都會擷取目前的應用程式 Context
,
您要包裝的 Intent
,以及一或多個指定
應如何使用意圖 (例如是否可重複使用意圖)。
若要進一步瞭解如何使用待處理意圖,請參閱 通知 和 App Widgets API 指南。
指定可變動性
如果您的應用程式指定 Android 12 以上版本,您就必須指定
應用程式所建立的每個 PendingIntent
物件的可變動性。如要宣告
指定的 PendingIntent
物件為可變動或不可變動,請使用
PendingIntent.FLAG_MUTABLE
或
PendingIntent.FLAG_IMMUTABLE
旗標。
如果應用程式嘗試建立 PendingIntent
物件
如未設定可變動標記
IllegalArgumentException
和
Logcat 中會顯示下列訊息:
PACKAGE_NAME: Targeting S+ (version 31 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.
盡可能建立不可變動的待處理意圖
在大多數情況下,應用程式應建立不可變動的 PendingIntent
物件,如
如以下程式碼片段所示。如果 PendingIntent
物件不可變動
則其他應用程式就無法修改意圖,以調整叫用
意圖。
Kotlin
val pendingIntent = PendingIntent.getActivity(applicationContext, REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE)
Java
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE);
不過,某些用途需要改為需要可變動的 PendingIntent
物件:
- 支援以下的直接回覆動作:
通知。
直接回覆需要變更 PendingIntent 物件中的片段資料
與回覆有關一般而言,您必須傳送
FILL_IN_CLIP_DATA
做為標記fillIn()
方法。 - 使用
CarAppExtender
。 - 使用執行個體將對話放在對話框中
(共
PendingIntent
個)。可變動的PendingIntent
物件可讓系統 正確標記,例如FLAG_ACTIVITY_MULTIPLE_TASK
和FLAG_ACTIVITY_NEW_DOCUMENT
。 - 撥打電話,要求取得裝置位置資訊
requestLocationUpdates()
敬上 或類似的 API可變動的PendingIntent
物件可讓系統 代表位置生命週期事件的意圖額外項目。這類事件包括 並有供應商提供服務。 - 使用「
AlarmManager
」設定鬧鐘時間。 可變動的PendingIntent
物件可讓系統EXTRA_ALARM_COUNT
意圖額外項目這項額外資料代表週期性鬧鐘的次數 加入這些額外項目後,意圖便能準確通知 應用程式偵測是否多次觸發週期性鬧鐘,例如 裝置休眠時。
如果應用程式會建立可變動的 PendingIntent
物件,則強烈建議您
使用明確意圖,並在
ComponentName
。如此一來
其他應用程式會叫用 PendingIntent
,並將控制項回傳至您的應用程式,
應用程式中的相同元件一律會啟動
在待處理意圖中使用明確意圖
如要更妥善地定義其他應用程式如何使用您應用程式的待處理意圖,請一律 包裝待處理意圖。 為符合這項最佳做法,請完成下列步驟:
- 檢查基本意圖的動作、套件和元件欄位 是否有設定。
-
使用
FLAG_IMMUTABLE
, ),用來建立待處理意圖。這個標記 防止收到PendingIntent
的應用程式填入資料 屬性。如果應用程式的minSdkVersion
22
或更低的級別,可以同時提供安全性和相容性 使用下列程式碼:if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
意圖解析
當系統收到隱含意圖來啟動活動時,會搜尋 將意圖與意圖篩選器進行比較,根據三個層面來判定意圖最出色的活動:
- 開拍
- 資料 (URI 和資料類型)。
- 類別:
以下各節說明如何將意圖對應至適當的元件 讓應用程式符合應用程式資訊清單檔案中的意圖篩選器宣告。
動作測試
如要指定可接受的意圖動作,意圖篩選器可以宣告 0 個以上
<action>
元素,如以下範例所示:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
如要通過這個篩選器,請在 Intent
中指定的動作
必須符合篩選器所列的其中一項動作。
如果篩選器並未列出任何動作,表示沒有
要比對的意圖相符,所以所有意圖都會未通過測試。不過,如果 Intent
未指定動作,只要篩選器就會通過測試即可
包含至少一個動作。
類別測試
如要指定可接受的意圖類別,意圖篩選器可以宣告 0 個以上
<category>
元素,如以下範例所示:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
為了傳遞類別測試,Intent
中的每個類別
必須符合篩選器中的類別。不需要反向操作,意圖篩選器可能會
宣告的類別數量超過 Intent
和
Intent
未通過。因此,沒有類別的意圖
無論篩選器中宣告的類別為何,一律會通過這項測試。
注意:
Android 會自動套用 CATEGORY_DEFAULT
類別
並傳遞至 startActivity()
和 startActivityForResult()
的所有隱含意圖。
如要讓活動接收隱含意圖,
在意圖篩選器中加入 "android.intent.category.DEFAULT"
的類別,如
與上一個 <intent-filter>
範例所示
資料測試
如要指定可接受的意圖資料,意圖篩選器可以宣告 0 個以上
<data>
元素,如以下範例所示:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
每<data>
元素可以指定 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
。
這些屬性在 <data>
元素中皆為選用屬性,
但具有線性依附元件:
- 如未指定配置,系統會忽略主機。
- 如未指定主機,系統會忽略通訊埠。
- 如果未同時指定配置和主機,系統會忽略路徑。
將意圖中的 URI 與篩選器中的 URI 規格進行比較時, 只會與篩選器中的 URI 部分進行比較例如:
- 如果篩選器僅指定配置,則所有具有該配置的 URI 篩選器。
- 如果篩選器指定了配置和授權,但沒有路徑,則所有 URI 但無論路徑與主機名稱相同,系統都會通過篩選器。
- 如果篩選器指定了配置、授權單位和路徑,則只有具有相同配置的 URI 授權,路徑則會通過篩選器
注意:路徑規格 包含萬用字元星號 (*),只要求部分路徑名稱相符。
資料測試會將意圖中的 URI 和 MIME 類型與 URI 進行比較 和 MIME 類型。規則如下:
- 未包含 URI 和 MIME 類型的意圖會傳遞 只在篩選器未指定任何 URI 或 MIME 類型時執行測試。
- 包含 URI 但沒有 MIME 類型的意圖 (無法從 URI) 只有在 URI 符合篩選器 URI 格式時,才會通過測試 而且篩選器同樣不會指定 MIME 類型。
- 包含 MIME 類型但沒有 URI 的意圖通過測試 只有在篩選器列出相同的 MIME 類型,且未指定 URI 格式時。
- 包含 URI 和 MIME 類型的意圖 (可從
URI) 僅會在 MIME 類型部分通過測試時傳送
類型與篩選器中列出的類型相符。它會通過測試的 URI 部分
或是 URI 與篩選器中的 URI 相符,或是具有
content:
或file:
URI,而且篩選器不會指定 URI。也就是 並假設元件支援content:
和file:
資料 (如有) 篩選器「只會」列出 MIME 類型。
注意:如果意圖指定了 URI 或 MIME 類型,資料測試會
如果 <intent-filter>
中沒有 <data>
元素,就會失敗。
最後一項規則 (d) 反映了期望
該元件可從檔案或內容供應器取得本機資料。
因此,他們的篩選器可以列出資料類型,不需要明確指定
命名 content:
和 file:
配置。
以下範例顯示 <data>
元素的一般情況
告知 Android 該元件可以從內容取得圖片資料
並顯示:
<intent-filter> <data android:mimeType="image/*" /> ... </intent-filter>
會套用的篩選器 指定資料類型,但不是 URI 最常見,因為 數據則是由內容供應者支付
另一個常見的設定是具有配置和資料類型的篩選器。適用對象
例如 <data>
這類元素會通知 Android
元件可以從網路擷取影片資料,才能執行動作:
<intent-filter> <data android:scheme="http" android:mimeType="video/*" /> ... </intent-filter>
意圖比對
不僅會將意圖與意圖篩選器比對,還能與意圖篩選器比對,
啟動 元件,也可探索一組相關資訊
元件舉例來說,Google Home 應用程式會填入應用程式啟動器
方法是找出所有具有意圖篩選器的活動
ACTION_MAIN
個動作和
CATEGORY_LAUNCHER
類別。
只有在意圖比對中的動作和類別時,比對作業才會成功
使用篩選器比對篩選器,如 IntentFilter
說明文件中所述
類別
您的應用程式可以使用意圖比對的方式,類似於 Google Home 應用程式的功能。
PackageManager
有一組 query...()
方法,這些方法會傳回所有可接受特定意圖的元件
一系列類似的 resolve...()
方法,
回應意圖例如:
queryIntentActivities()
會傳回可執行的所有活動清單
做為引數傳遞的意圖,而 queryIntentServices()
會傳回類似的服務清單。
這兩種方法都不會啟動元件;只會列出
回應。方法也很類似
queryBroadcastReceivers()
,適用於廣播接收器。