意圖是安卓中重要核心組件之一。
Intent 是一個消息傳遞對象,您可以使用它從其他應(yīng)用組件請求操作。盡管 Intent 可以通過多種方式促進(jìn)組件之間的通信礁扮,但其基本用例主要包括以下三個:
- 啟動 Activity
- 啟動服務(wù)
- 傳遞廣播
Intent 分為兩種類型:
- 顯式 Intent:按名稱(完全限定類名)指定要啟動的組件。 通常瞬沦,您會在自己的應(yīng)用中使用顯式 Intent 來啟動組件太伊,這是因?yàn)槟酪獑拥?Activity 或服務(wù)的類名。例如逛钻,啟動新 Activity 以響應(yīng)用戶操作僚焦,或者啟動服務(wù)以在后臺下載文件。
- 隱式 Intent :不會指定特定的組件曙痘,而是聲明要執(zhí)行的常規(guī)操作芳悲,從而允許其他應(yīng)用中的組件來處理它。 例如边坤,如需在地圖上向用戶顯示位置名扛,則可以使用隱式 Intent,請求另一具有此功能的應(yīng)用在地圖上顯示指定的位置茧痒。
[圖片上傳失敗...(image-976dbc-1640352429584)]
肮韧,并將其傳遞給 startActivity()。[2]Android 系統(tǒng)搜索所有應(yīng)用中與 Intent 匹配的 Intent 過濾器。** 找到匹配項(xiàng)之后弄企,[3] 該系統(tǒng)通過調(diào)用匹配 Activity(Activity B)的 onCreate() 方法并將其傳遞給 Intent超燃,以此啟動匹配 Activity](http://upload-images.jianshu.io/upload_images/1662509-6496761370a9e66c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
注意:為了確保應(yīng)用的安全性,啟動 Service
時桩蓉,請始終使用顯式 Intent淋纲,且不要為服務(wù)聲明 Intent 過濾器劳闹。使用隱式 Intent 啟動服務(wù)存在安全隱患院究,因?yàn)槟鸁o法確定哪些服務(wù)將響應(yīng) Intent,且用戶無法看到哪些服務(wù)已啟動本涕。從 Android 5.0(API 級別 21)開始业汰,如果使用隱式 Intent 調(diào)用 [bindService()](http://developer.android.youdaxue.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int)),系統(tǒng)會引發(fā)異常菩颖。
顯式 Intent 示例
顯式 Intent 是指用于啟動某個特定應(yīng)用組件(例如样漆,應(yīng)用中的某個特定 Activity 或服務(wù))的 Intent。 要創(chuàng)建顯式 Intent晦闰,請為 Intent 對象定義組件名稱 — Intent 的所有其他屬性均為可選屬性放祟。
例如,如果在應(yīng)用中構(gòu)建了一個名為 DownloadService呻右、旨在從網(wǎng)頁下載文件的服務(wù)跪妥,則可使用以下代碼啟動該服務(wù):
// Executed in an Activity, so 'this' is the Context
// 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 示例
注意:用戶可能沒有任何應(yīng)用處理您發(fā)送到 startActivity() 的隱式 Intent。如果出現(xiàn)這種情況声滥,則調(diào)用將會失敗眉撵,且應(yīng)用會崩潰。要驗(yàn)證 Activity 是否會接收 Intent落塑,請對 Intent 對象調(diào)用 resolveActivity()纽疟。如果結(jié)果為非空,則至少有一個應(yīng)用能夠處理該 Intent憾赁,且可以安全調(diào)用startActivity()污朽。 如果結(jié)果為空,則不應(yīng)使用該 Intent龙考。如有可能蟆肆,您應(yīng)停用發(fā)出該 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);
}
強(qiáng)制使用應(yīng)用選擇器
如果有多個應(yīng)用響應(yīng)隱式 Intent洲愤,則用戶可以選擇要使用的應(yīng)用颓芭,并將其設(shè)置為該操作的默認(rèn)選項(xiàng)。 如果用戶可能希望今后一直使用相同的應(yīng)用執(zhí)行某項(xiàng)操作(例如柬赐,打開網(wǎng)頁時亡问,用戶往往傾向于僅使用一種網(wǎng)絡(luò)瀏覽器),則這一點(diǎn)十分有用。
但是州藕,如果多個應(yīng)用可以響應(yīng) Intent束世,且用戶可能希望每次使用不同的應(yīng)用,則應(yīng)采用顯式方式顯示選擇器對話框床玻。 選擇器對話框每次都會要求用戶選擇用于操作的應(yīng)用(用戶無法為該操作選擇默認(rèn)應(yīng)用)毁涉。 例如,當(dāng)應(yīng)用使用ACTION_SEND 操作執(zhí)行“共享”時锈死,用戶根據(jù)目前的狀況可能需要使用另一不同的應(yīng)用贫堰,因此應(yīng)當(dāng)始終使用選擇器對話框,如圖 2 中所示待牵。要顯示選擇器其屏,請使用 [createChooser()](http://developer.android.youdaxue.com/reference/android/content/Intent.html#createChooser(android.content.Intent, java.lang.CharSequence)) 創(chuàng)建 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);
}
使用待定 Intent
PendingIntent 對象是 Intent 對象的包裝器。PendingIntent 的主要目的是授權(quán)外部應(yīng)用使用包含的 Intent贰拿,就像是它從您應(yīng)用本身的進(jìn)程中執(zhí)行的一樣蛤袒。
待定 Intent 的主要用例包括:
- 聲明用戶使用您的通知執(zhí)行操作時所要執(zhí)行的 Intent(Android 系統(tǒng)的 NotificationManager 執(zhí)行 Intent)。
- 聲明用戶使用您的 應(yīng)用小部件執(zhí)行操作時要執(zhí)行的 Intent(主屏幕應(yīng)用執(zhí)行 Intent
)膨更。 - 聲明未來某一特定時間要執(zhí)行的 Intent(Android 系統(tǒng)的 AlarmManager 執(zhí)行 Intent)妙真。
由于每個 Intent 對象均設(shè)計為由特定類型的應(yīng)用組件(Activity、Service 或 BroadcastReceiver)進(jìn)行處理询一,因此還必須基于相同的考慮因素創(chuàng)建PendingIntent隐孽。使用待定 Intent 時,應(yīng)用不會使用調(diào)用(如 startActivity())執(zhí)行該 Intent健蕊。相反菱阵,通過調(diào)用相應(yīng)的創(chuàng)建器方法創(chuàng)建PendingIntent 時,您必須聲明所需的組件類型:
除非您的應(yīng)用正在從其他應(yīng)用中接收待定 Intent缩功,否則上述用于創(chuàng)建 PendingIntent 的方法可能是您所需的唯一 PendingIntent 方法晴及。
每種方法均會提取當(dāng)前的應(yīng)用 Context、您要包裝的 Intent 以及一個或多個指定應(yīng)如何使用該 Intent 的標(biāo)志(例如嫡锌,是否可以多次使用該 Intent)虑稼。
如需了解有關(guān)使用待定 Intent 的詳細(xì)信息,請參閱通知和應(yīng)用小部件 API 指南等手冊中每個相應(yīng)用例的相關(guān)文檔势木。
Intent 解析
當(dāng)系統(tǒng)收到隱式 Intent 以啟動 Activity 時蛛倦,它根據(jù)以下三個方面將該 Intent 與 Intent 過濾器進(jìn)行比較,搜索該 Intent 的最佳 Activity:
- Intent 操作
- Intent 數(shù)據(jù)(URI 和數(shù)據(jù)類型)
- Intent 類別
下文根據(jù)如何在應(yīng)用的清單文件中聲明 Intent 過濾器啦桌,描述 Intent 如何與相應(yīng)的組件匹配溯壶。
Intent 匹配
通過 Intent 過濾器匹配 Intent及皂,這不僅有助于發(fā)現(xiàn)要激活的目標(biāo)組件,還有助于發(fā)現(xiàn)設(shè)備上組件集的相關(guān)信息且改。 例如验烧,主頁應(yīng)用通過使用指定ACTION_MAIN 操作和 CATEGORY_LAUNCHER 類別的 Intent 過濾器查找所有 Activity,以此填充應(yīng)用啟動器又跛。
您的應(yīng)用可以采用類似的方式使用 Intent 匹配碍拆。PackageManager 提供了一整套 query...() 方法來返回所有能夠接受特定 Intent 的組件。此外慨蓝,它還提供了一系列類似的 resolve...() 方法來確定響應(yīng) Intent 的最佳組件感混。 例如,[queryIntentActivities()](http://developer.android.youdaxue.com/reference/android/content/pm/PackageManager.html#queryIntentActivities(android.content.Intent, int)) 將返回能夠執(zhí)行那些作為參數(shù)傳遞的 Intent 的所有 Activity 列表菌仁,而 [queryIntentServices()](http://developer.android.youdaxue.com/reference/android/content/pm/PackageManager.html#queryIntentServices(android.content.Intent, int)) 則可返回類似的服務(wù)列表浩习。這兩種方法均不會激活組件,而只是列出能夠響應(yīng)的組件济丘。 對于廣播接收器,有一種類似的方法: [queryBroadcastReceivers()](http://developer.android.youdaxue.com/reference/android/content/pm/PackageManager.html#queryBroadcastReceivers(android.content.Intent, int))洽蛀。