Android中Intent和Intent过滤器详解
眾所周知,Android開(kāi)發(fā)中,Intent是個(gè)比較常見(jiàn)的應(yīng)用組件,今天,我就參考Google官方文檔書寫一次詳細(xì)的從頭到尾的博文。
*Intent是一個(gè)消息傳遞對(duì)象,可以使用它從其他應(yīng)用組件請(qǐng)求操作,基本用例包括啟動(dòng)Activity、啟動(dòng)服務(wù)和傳遞廣播。
*Intent分為兩種類型:顯式Intent和隱式Intent。
顯式Intent是完全限定類名指定要啟動(dòng)的組件,通常是在自己的應(yīng)用中使用顯示Intent,因?yàn)樽约褐酪獑?dòng)的Activity或者服務(wù)的類名。創(chuàng)建顯式Intent啟動(dòng)Activity或者服務(wù)時(shí),系統(tǒng)將立即啟動(dòng)指定的應(yīng)用組件。
隱式Intent不會(huì)指定特定的組件,而是聲明要執(zhí)行的操作,從而允許其他應(yīng)用中的組件來(lái)處理。創(chuàng)建隱式Intent時(shí),系統(tǒng)將Intent內(nèi)容與設(shè)備上其他應(yīng)用的清單文件中聲明的Intent過(guò)濾器進(jìn)行比較,從而找到要啟動(dòng)的應(yīng)用程序,若Intent與Intent過(guò)濾器匹配,系統(tǒng)將啟動(dòng)該組件,并向其傳遞Intent對(duì)象,若有多個(gè)Intent過(guò)濾器匹配,則系統(tǒng)會(huì)顯示對(duì)話框,支持用戶選取將要使用的應(yīng)用。
Intent過(guò)濾器是應(yīng)用清單文件中的一個(gè)表達(dá)式,它指定該組件要接收的Intent類型,通過(guò)為Activity聲明Intent過(guò)濾器,之后就可以在其他應(yīng)用程序中直接使用某一特定類型的Intent啟動(dòng)Activity,若沒(méi)有為Activity聲明Intent過(guò)濾器,則Activity只能通過(guò)顯示Intent啟動(dòng)。
(注意:由于使用隱式Intent時(shí),無(wú)法確定哪些服務(wù)獎(jiǎng)響應(yīng)Intent,故使用隱式Intent存在安全隱患,為了確保應(yīng)用的安全,啟動(dòng)Service時(shí),務(wù)必始終使用顯示Intent)
構(gòu)建Intent
Intent中包含:組件名稱、操作、數(shù)據(jù)、類別、Extra、標(biāo)志。
組件名稱,是可選項(xiàng),若沒(méi)有組件名稱則Intent是隱式的。(注,啟動(dòng)service時(shí),應(yīng)始終指定組件名稱)可以使用setComponent(), sestClass(), setClassName()或Intent構(gòu)造函數(shù)設(shè)置組件名稱。
操作,在很大程度上決定其余Intent的構(gòu)成,特別是數(shù)據(jù)和Extra中的內(nèi)容??梢灾付ㄗ约旱牟僮?#xff0c;但通常是使用由Intent類或其他框架類定義的操作常量。啟動(dòng)Activity的常見(jiàn)操作是:ACTION_VIEW, ACTION_SEND等。
數(shù)據(jù),創(chuàng)建Intent時(shí),最好是同時(shí)指定URI和數(shù)據(jù)類型(MIME類型)。設(shè)置數(shù)據(jù)URI調(diào)用setData(),設(shè)置MIME類型調(diào)用setType(),若同時(shí)設(shè)置二者調(diào)用setDataAndType()。
類別,大多數(shù)Intent不需要類別,常見(jiàn)的類別有CATEGORY_BROWSABLE, CATEGORY_LAUNCHER等。
Extra,可以使用各種putExtra()方法添加extra數(shù)據(jù),每種方法均接受兩個(gè)參數(shù):鍵名和值,還可以創(chuàng)建一個(gè)包含所有extra數(shù)據(jù)的Bundle對(duì)象,然后使用putExtras()將Bundle插入Intent中。
標(biāo)志,可以指示Android系統(tǒng)如何啟動(dòng)Activity,以及啟動(dòng)后如何處理。setFlag()
顯式Intent示例:
Intent intent = new Intent(this, Example.class); intent.setData(Uri.parse(uri)); //uri為一個(gè)stringURI startService(intent);隱式Intent示例:
需要注意,用戶可能沒(méi)有任何應(yīng)用處理發(fā)送到startActivity()的隱式Intent,若出現(xiàn)這種情況,則調(diào)用將會(huì)失敗,且程序會(huì)崩潰,所以,使用隱式Intent一定要注意驗(yàn)證Activity是否會(huì)接收到Intent,對(duì)Intent對(duì)象調(diào)用resolveActivity()方法,若結(jié)果非空,則至少有一個(gè)應(yīng)用能處理該Intent,且可以安全調(diào)用startActivity(),若結(jié)果為空,則不應(yīng)使用這個(gè)Intent,此時(shí)若可能,應(yīng)停用發(fā)出該Intent的功能。
Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_TEXT, textMessage); intent.setType("text/plain"); if(intent.resolveActivity(getPackageManager()!=null){startActivity(intent); }在調(diào)用startActivity()時(shí),系統(tǒng)將檢查已安裝的所有應(yīng)用,確定哪些應(yīng)用能夠處理這種Intent(即:含有ACTION_SEND操作并攜帶”text/plain“數(shù)據(jù)的Intent)。
強(qiáng)制使用應(yīng)用選擇器:
若要顯示選擇器,使用createChooser()創(chuàng)建Intent,并將其傳遞給startActivity():
Intent sendIntent = new Intent(Intent.ACTION_SEND); //使用string類型的資源作為UI文本。 String title = getResources().getString(R.string.choose_title); Intent chooser = Intent.createChooser(sendIntent, title); if(sendIntent.resolveActivity(getPackageManager()!= null){startActivity(chooser); }
這將顯示一個(gè)對(duì)話框,其中有響應(yīng)傳遞給createChooser()方法的Intent應(yīng)用列表,并且將提供的文本用作對(duì)話框標(biāo)題。
接收隱式Intent:
每個(gè)Intent過(guò)濾器均由應(yīng)用清單文件中的<intent-filter>元素定義,并嵌套在相應(yīng)的應(yīng)用文件中,在<intent-filter>內(nèi)部,可以使用以下三個(gè)元素中一個(gè)或多個(gè)指定要接受的Intent類型:
<action>, 在name屬性中,聲明接受的Intent操作,該值必須是操作的文本字符串值,而不是類常量。
<data>, 使用一個(gè)或多個(gè)指定數(shù)據(jù)URI各個(gè)方面(scheme、host、port、path等)和MIME類型的屬性,聲明接受的數(shù)據(jù)類型。
<category>, 在name屬性中,聲明接受的Intent類別,該值必須是操作的文本字符串值,而不是類常量。
注意,為了接收隱式Intent,必須將CATEGORY_DEFAULT類別包括在Intent過(guò)濾器中,startActivity()和startActivityForResult()將按照已聲明CATEGORY_DEFAULT類別的方式處理所有Intent,若未在Intent過(guò)濾器中聲明此類別,則隱式Intent不會(huì)解析Activity。
以下是一個(gè)使用包含Intent過(guò)濾器的Activity聲明,當(dāng)數(shù)據(jù)類型為文本時(shí),系統(tǒng)將接受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>特別說(shuō)明:
使用Intent過(guò)濾器時(shí),無(wú)法安全地方式其他應(yīng)用啟動(dòng)組件,盡管Intent過(guò)濾器將組件限制為僅響應(yīng)特定類型的隱式Intent,但如果開(kāi)發(fā)者確定您的組件名稱,則其他應(yīng)用有可能通過(guò)使用顯示Intent啟用你的應(yīng)用組件,如果必須確保只有自己的應(yīng)用才能啟動(dòng)的某一組件,則針對(duì)該組件將exported屬性設(shè)置為false。
對(duì)于所有Activity,必須在清單文件中聲明Intent過(guò)濾器牡丹石廣播接收器的過(guò)濾器可以通過(guò)調(diào)用registerReceiver()動(dòng)態(tài)注冊(cè)。稍后可以使用unregisterReceiver()注銷該接收器, 這樣應(yīng)用便可以僅在應(yīng)用運(yùn)行時(shí)的某一指定時(shí)間段內(nèi)偵聽(tīng)特定的廣播。
過(guò)濾器示例:
下面是一個(gè)社交共享應(yīng)用的清單文件中的片段:
<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>第一個(gè)ActivityMainActivity是應(yīng)用的主要入口點(diǎn),當(dāng)用戶最初使用啟動(dòng)器圖標(biāo)啟動(dòng)應(yīng)用時(shí),該Activity將打開(kāi):
ACTION_MAIN操作指示這里是主要入口點(diǎn),且不要求輸入任何Intent數(shù)據(jù)。
CATEGORY_LAUNCHER類別指示此Activity的圖標(biāo)應(yīng)放入系統(tǒng)的應(yīng)用啟動(dòng)器,若<activity>元素未使用icon指定圖標(biāo),則系統(tǒng)將使用<application>元素中的圖標(biāo)。
這兩個(gè)元素必須配對(duì)使用,Activity才會(huì)顯示在應(yīng)用啟動(dòng)器中。
第二個(gè)Activity ShareActivity 旨在便于共享文本和媒體內(nèi)容。盡管用戶可以通過(guò)從MainActivity導(dǎo)航進(jìn)入此Activity,但也可以從發(fā)出隱式Intent的另一應(yīng)用中直接進(jìn)入ShareActivity。
注:MIME類型application/vnd.google.panorama360+jpg是一個(gè)指定全景照片的特殊數(shù)據(jù)類型,可以使用Google panoramaAPI對(duì)其進(jìn)行處理。
使用待定Intent:
PendingIntent對(duì)象是Intent對(duì)象的包裝器,PendingIntent的主要目的是授權(quán)外部應(yīng)用使用包含的Intent,就像是它從應(yīng)用本身的進(jìn)程中執(zhí)行一樣。
待定Intent的主要用例包括:
*聲明用戶使用通知執(zhí)行操作時(shí)所要執(zhí)行的Intent(Android系統(tǒng)的NotificationManager執(zhí)行Intent)。
*聲明用戶使用應(yīng)用小部件執(zhí)行操作時(shí)要執(zhí)行的Intent(主屏幕應(yīng)用執(zhí)行Intent)。
*聲明未來(lái)某一特定時(shí)間要執(zhí)行的Intent(Android系統(tǒng)的AlarmManger執(zhí)行Intent)。
由于每個(gè)Intent對(duì)象均設(shè)計(jì)為由特定類型的應(yīng)用組件(Activity、Service或BroadcastReceiver)進(jìn)行處理,因此還必須基于相同的考慮因素創(chuàng)建PendingIntent。
*PendingIntent.getActivity(),適用于啟動(dòng)Activity的Intent。
*PendingIntent.getService(),適用于啟動(dòng)Service的Intent。
*PendingIntent.getBroadcast(),適用于啟動(dòng)BroadcastReceiver的Intent。
Intent解析:
當(dāng)系統(tǒng)收到隱式Intent啟動(dòng)Activity時(shí),根據(jù)以下三個(gè)方面將該Intent與Intent過(guò)濾器進(jìn)行比較,搜索該Intent的最佳Activity:
*Intent 操作 <action android:name="android.intent.action.EDIT/>
*Intent 數(shù)據(jù)(URI和數(shù)據(jù)類型)<category android:name="android.intent.category.DEFAULT"/>
*Intent 類別 <data android:mimeType="audio/mpeg"android:scheme="http".../>
<data android:mimeType="image/*"/>
總結(jié)
以上是生活随笔為你收集整理的Android中Intent和Intent过滤器详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android项目中Bluetooth类
- 下一篇: Android中Activity总结