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