Intents and Intent Filters

來自 :http://flysnow.iteye.com/blog/961576

在這裏你將會學到:

  1. 什麼是Intent和Intent Filter
  2. Intent和Intent Filter有什麼用
  3. 怎麼啓動(傳遞)一個Intent
  4. Intent裏包含什麼
  5. 什麼是顯式Intent以及什麼隱式Intent
  6. Intent是怎樣匹配的

一:前言

     在正式介紹Intent之前,我們先看下上面說的Activity、Service和Broadcast Receiver是怎樣傳遞Intent。對於這三個組件而言,他們都有自己獨立的傳遞Intent的機制:

  1. Activity:對於Activity來說,它主要是通過Context.startActivity() 或Activity.startActivityForRestult() 來啓動一個存在的Activity做一些事情。當使用Activity.startActivityForResult() 啓動一個Activity時,可以使用Activity.setResult()返回一些結果信息,可以在Activity.onActivityResult() 中得到返回的結果.
  2. Service:對於Service來說,它主要是通過Context.startService() 初始化一個Service或者傳遞消息給正在運行的Service。同樣,也可以通過Context.bindService() 建立一個調用組件和目標服務之間的連接。
  3. Broadcast Receiver:我們可以通過 Context.sendBroadcast() , Context.sendOrderedBroadcast() 以及Context.sendStickyBroadcast() 這些方法,傳遞Intent給感興趣的廣播。

     消息之間的傳遞是沒有重疊的,比如調用startActivity()傳播一個Intent,只會傳播給Activity,而不會傳播給Service和Broadcast Receiver,反過來也是這樣的。

二:Intent對象

      一個Intent對象包含了很多數據的信息,比如要執行的動作,類別,數據,附加信息等等,下面就一一列列出一個Intent中包含的信息。

組件名稱

      這個組件名稱字段其實就是一個ComponentName類,它包含了一個目標組件的全限定名,比如com.flysnow.intent.Activity1,這就是一個全限定名的Activity。組件名字可以通過setComponent()、setClass()或者setClassName()設置,如果設置了Intent目標組件的名字,那麼這個Intent就會被傳遞給特定的組件,也就是我們說的顯式Intent.如果不設置,則是隱式的Intent,Android系統將根據Intent Filter中的信息進行匹配.

Action(動作)

       一個Intent的Action在很大程度上說明這個Intent要做什麼,是查看(View)、刪除(Delete)、編輯(Edit)等等。Action一個字符串命名的動作,Android中預定義了很多Action,可以參考Intent類查看,下面是文檔中的幾個動作



     當然,我們也可以自定義Action,比如com.flysnow.intent.ACTION_ADD,定義Action的時候最好能表明意思,要做什麼,這樣我們的Intent中的數據纔好填充。Intent對象的getAction()可以獲取動作,使用setAction()可以設置動作。

Data(數據)

      Data,其實就是一個URI,用於執行一個Action時所用到的數據的URI和MIME。不同的Action有不同的數據規格,比如ACTION_EDIT動作,數據就可以能包含一個用於編輯文檔的URI,如果是一個ACTION_CALL動作,那麼數據就是一個包含了tel:6546541的數據字段,所以上面提到的自定義Action時要規範命名。數據的URI和類型對於Intent的匹配是很重要的,Android往往根據數據的URI和MIME找到能處理該Intent的最佳目標組件。

Category(類別)

     Category指定了用於處理Intent的組件的類型信息,一個Intent可以添加多個Category,使用addCategory()方法即可,使用removeCategory()刪除一個已經添加的類別。Android的Intent類裏定義了很多常用的類別,可以參考使用。

Extras(附加信息)

      有些用於處理Intent的目標組件需要一些額外的信息,那麼就可以通過Intent的put..()方法把額外的信息塞入到Intent對象中,用於目標組件的使用,一個附件信息就是一個key-value的鍵值對..Intent有一系列的put和get方法用於處理附加信息的塞入和取出。

Flag(標識)

     Android有很多標識,用於標記如何啓動一個活動,是NEW_TASK還是其他等等,以及啓動後怎麼對待這個活動。。可以參考Intent類中的FLAG常量字段。

三:Intent的解析

     介紹完了Intent對象的構成,就要介紹Android系統是怎樣解析Intent的,Android是怎麼傳遞Intent到目標組件的呢?

Intent分類

      Intent可以分爲兩類,一類是顯式的Intent,一類是隱式的Intent,上面有過提及。顯示的Intent就是指定了組件名字的,隱式的就是沒有指定Intent的組件名字,需要Android根據Intent中的Action、data、Category等來解析匹配。而目標組件(Activity、Service、Broadcast Receiver)怎通過設置他們的Intent Filter來界定其處理的Intent。如果一個組件沒有定義Intent Filter,那麼它只能接受處理顯示的Intent,只有定義了Intent Filter的組件才能同時處理隱式和顯示的Intent。

Action檢測

     爲了對Action的作用進行檢測,我們使用一個例子來演示Action的作用。項目名爲Intents,應用名爲Intents and Filters,運行在Android2.2版本上.主啓動Activity爲IntentsTestList

  1. IntentsTestList代碼如下:
    Java代碼  收藏代碼
    1. /** 
    2.  * Intents測試列表類 
    3.  * @author 飛雪無情 
    4.  * @since 2011-3-14 
    5.  */  
    6. public class IntentsTestList extends ListActivity {  
    7.     private String ACTION_VIEW="com.flysnow.intent.ACTION_VIEW";  
    8.     /** Called when the activity is first created. */  
    9.     @Override  
    10.     public void onCreate(Bundle savedInstanceState) {  
    11.         super.onCreate(savedInstanceState);  
    12.       //定義ListAdapter  
    13.         setListAdapter(new SimpleAdapter(this, getData(),  
    14.                 android.R.layout.simple_list_item_1, new String[] { "title" },new int[] {android.R.id.text1}));  
    15.         getListView().setTextFilterEnabled(true);  
    16.           
    17.         //註冊一個廣播  
    18.         super.registerReceiver(new BroadcastReceiver() {  
    19.               
    20.             @Override  
    21.             public void onReceive(Context context, Intent intent) {  
    22.                 Toast.makeText(context, "該Broadcast的Intent Filter值只設置了Action", Toast.LENGTH_SHORT).show();  
    23.             }  
    24.         },new IntentFilter(ACTION_VIEW));  
    25.     }  
    26.     @Override  
    27.     protected void onListItemClick(ListView l, View v, int position, long id) {  
    28.         Intent intent=(Intent)getData().get(position).get("intent");  
    29.         Boolean isActivity=(Boolean)getData().get(position).get("isActivity");  
    30.         if(isActivity){  
    31.             startActivity(intent);  
    32.         }else{  
    33.             sendBroadcast(intent);  
    34.         }  
    35.           
    36.     }  
    37.   
    38.     /** 
    39.      * 返回ListView需要的數據 
    40.      * @return ListView需要的數據 
    41.      */  
    42.     private List<Map<String,Object>> getData() {  
    43.         List<Map<String,Object>> data=new ArrayList<Map<String,Object>>();  
    44.         addItem(data, "空Action的Activity"new Intent(),true);  
    45.         addItem(data, "Action檢測-Activity"new Intent(ACTION_VIEW),true);  
    46.         addItem(data, "Action檢測-Broadcast"new Intent(ACTION_VIEW),false);  
    47.         return data;  
    48.     }  
    49.     /** 
    50.      * 給ListView添加數據 
    51.      * @param data 存儲數據的List 
    52.      * @param name 要顯示的Title 
    53.      * @param intent 單擊某一項時要啓動的Activity 
    54.      * @param isActivity 啓動的是否是Activity,true是,false爲廣播 
    55.      */  
    56.     private void addItem(List<Map<String,Object>> data, String name, Intent intent,boolean isActivity) {  
    57.         Map<String, Object> temp = new HashMap<String, Object>();  
    58.         temp.put("title", name);  
    59.         temp.put("intent", intent);  
    60.         temp.put("isActivity", isActivity);  
    61.         data.add(temp);  
    62.     }  
    63. }  
     這裏主要是使用ListActivity列出3個測試,一個測試空的Intent,一個測試只有Action的Intent--Activity版,一個測試只有Action的Intent--Broadcast版。。。
  2. 爲了測試startActivity(),我們新建一個Activity名字爲ActionActivity代碼如下:
    Java代碼  收藏代碼
    1. /** 
    2.  * @author 飛雪無情 
    3.  * @since 2011-3-14 
    4.  */  
    5. public class ActionActivity extends Activity {  
    6.   
    7.     @Override  
    8.     protected void onCreate(Bundle savedInstanceState) {  
    9.         super.onCreate(savedInstanceState);  
    10.         TextView text=new TextView(this);  
    11.         text.setText("該Activity的Intent Filter值只設置了Action");  
    12.         setContentView(text);  
    13.     }  
    14.       
    15. }  
     很簡單,只有一段文本的展示。
  3. AndroidManifest.xml修改如下:
    Xml代碼  收藏代碼
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    3.       package="com.flysnow.intent"  
    4.       android:versionCode="1"  
    5.       android:versionName="1.0">  
    6.     <uses-sdk android:minSdkVersion="8" />  
    7.   
    8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
    9.         <activity android:name=".IntentsTestList"  
    10.                   android:label="@string/app_name">  
    11.             <intent-filter>  
    12.                 <action android:name="android.intent.action.MAIN" />  
    13.                 <category android:name="android.intent.category.LAUNCHER" />  
    14.             </intent-filter>  
    15.         </activity>  
    16.         <activity android:name=".ActionActivity" android:label="Action檢測">  
    17.             <intent-filter>  
    18.                 <action android:name="com.flysnow.intent.ACTION_VIEW"></action>  
    19.                 <action android:name="android.intent.action.VIEW"></action>  
    20.                 <category android:name="android.intent.category.DEFAULT"></category>  
    21.             </intent-filter>  
    22.         </activity>  
    23.   
    24.     </application>  
    25. </manifest>  
     很簡單,爲我們的ActionContext加上了兩個action標籤和一個category標籤,加category標籤設置成android.intent.category.DEFAULT是爲了讓這個Activity可以接收隱式的Intent請求,這是Android規定的,對於Activity,使用Context.startActivity()傳遞隱式Intent,默認是包含了android.intent.category.DEFAULT的,所以定義的Activity要想接收,必須在Intent Filter裏添加android.intent.category.DEFAULT這個Category。
  4. 運行入下圖:

     當點擊“空Action的Activity”的時候,會報異常,因爲Intent什麼都沒有設置,沒有任何的Activity能處理它 。當點擊“Action檢測-Activity”的時候會打開我們的ActionActivity這個Activity,點擊“Action檢測-Broadcast”會彈出Toast提示,說明已經被接收到。。從上面我們可以看出,當Intent設置了Action時,只要對應的組件的Intent Filter中包含該Action的定義,那麼這個組件就會接收該Intent。。。 

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