2014年7月28日 星期一

Android中的意圖匹配--IntentFilter的作用

infor from: http://blog.csdn.net/dlutbrucezhang/article/details/8917774

【0】Android基本的設計理念是鼓勵減少組件間的耦合,因此Android提供了Intent (意圖) ,Intent提供了一種通用的消息系統,它允許在你的應用程序與其它的應用程序間傳遞Intent來執行動作和產生事件。使用Intent可以激活Android應用的三個核心組件:活動、服務和廣播接收器。

【1】Intent可以劃分成顯式意圖和隱式意圖。
顯式意圖:調用Intent.setComponent()或Intent.setClass()方法明確指定了組件名的Intent為顯式意圖,顯式意圖明確指定了Intent應該傳遞給哪個組件。

隱式意圖:沒有明確指定組件名的Intent為隱式意圖。Android系統會根據隱式意圖中設置的動作(action)、類別(category)、數據(URI和數據類型)找到最合適的組件來處理這個意圖。
【2】對於隱式意圖,Android是怎樣尋找到這個最合適的組件呢?
記的前面我們在定義活動時,指定了一個intent-filter,Intent Filter(意圖過濾器)其實就是用來匹配隱式Intent的,當一個意圖對像被一個意圖過濾器進行匹配測試時,只有三個方面會被參考到:動作、數據(URI以及數據類型)和類別。

1.動作測試

<intent-filter>元素中可以包括子元素<action>,比如:
<intent-filter> 
<action android:name=”com.example.project.SHOW_CURRENT” /> 
<action android:name=”com.example. project.SHOW_RECENT” /> 
<action android:name=”com.example.project.SHOW_PENDING” /> 
</intent-filter> 
一條<intent-filter>元素至少應該包含一個<action>,否則任何Intent請求都不能和該<intent-filter>匹配。如果Intent請求的Action和<intent-filter>中個某一條<action>匹配,那麼該Intent就通過了這條<intent-filter>的動作測試。如果Intent請求或<intent-filter>中沒有說明具體的Action類型,那麼會出現下面兩種情況。
(1)如果<intent-filter>中沒有包含任何Action類型,那麼無論什麼Intent請求都無法和這條<intent- filter>匹配;
(2)反之,如果Intent請求中沒有設定Action類型,那麼只要<intent-filter>中包含有Action類型,這個Intent請求就將順利地通過<intent-filter>的行為測試。

2.數據測試

數據在<intent-filter>中的描述如下:
<intent-filter . . . > 
<data android:type=”video/mpeg” android:scheme=”http” . . . /> 
<data android:type=” audio/mpeg” android:scheme=”http” . . . /> 
</intent-filter> 
<data>元素指定了希望接受的Intent請求的數據URI和數據類型,URI被分成三部分來進行匹配:scheme 、 authority和path。其中,用setData()設定的Inteat請求的URI數據類型和scheme必須與IntentFilter中所指定的一致。若IntentFilter中還指定了authority或path,它們也需要相匹配才會通過測試。
數據測試同時比較意圖對象和過濾器中指定的URI和數據類型。
規則如下:
a. 一個既不包含URI也不包含數據類型的意圖對象僅在過濾器也同樣沒有指定任何URIs和數據類型的情況下才能通過測試。
b. 一個包含URI但沒有數據類型的意圖對象僅在它的URI和一個同樣沒有指定數據類型的過濾器裡的URI匹配時才能通過測試。這通常發生在類似於mailto:和tel:這樣的URIs上:它們並不引用實際數據。
c. 一個包含數據類型但不包含URI的意圖對象僅在這個過濾器列舉了同樣的數據類型而且也沒有指定一個URI的情況下才能通過測試。
d. 一個同時包含URI和數據類型(或者可從URI推斷出數據類型)的意圖對象可以通過測試,如果它的類型和過濾器中列舉的類型相匹配的話。如果它的URI和這個過濾器中的一個URI相匹配或者它有一個內容content:或者文件fil​​e: URI而且這個過濾器沒有指定一個URI,那麼它也能通過測試。換句話說,一個組件被假定為支持content:和file: 數據如果它的過濾器僅列舉了一個數據類型。


3.類別測試

<intent-filter>元素可以包含<category>子元素,比如:
<intent-filter . . . > 
<category android:name=”android.Intent.Category.DEFAULT” /> 
<category android:name=”android. Intent.Category.BROWSABLE” /> 
</intent-filter> 
只有當Intent請求中所有的Category與組件中某一個IntentFilter的<category>完全匹配時,才會讓該Intent請求通過測試,IntentFilter中多餘的< category>聲明並不會導致匹配失敗。一個沒有指定任何類別測試的IntentFilter僅僅只會匹配沒有設置類別的Intent請求。
對於一個能夠通過類別匹配測試的意圖,意圖對像中的類別必須匹配過濾器中的類別。這個過濾器可以列舉另外的類別,但它不能遺漏在這個意圖中的任何類別。
原則上一個沒有類別的意圖對象應該總能夠通過匹配測試,而不管過濾器裡有什麼。大部分情況下這個是對的。但有一個例外,Android把所有傳給startActivity()的隱式意圖當作他們包含至少一個類別:"android.intent.category.DEFAULT" (CATEGORY_DEFAULT常量)。因此,想要接收隱式意圖的​​活動必須在它們的意圖過濾器中包含"android.intent.category.DEFAULT"。(帶"android.intent.action.MAIN"和"android.intent.category.LAUNCHER"設置的過濾器是例外)


  1. <span style= "background-color: rgb(255, 255, 255);" ><span style= "font-size:18px;"><strong> public  class  MainActivity  extends  Activity   
  2. {  
  3.     /** Called when the activity is first created. */  
  4.     @Override       
  5.     public  void  onCreate(Bundle savedInstanceState)   
  6.     {  
  7.         super .onCreate(savedInstanceState);  
  8.         setContentView(R.layout.main);  
  9.           
  10.         Button button = (Button)  this .findViewById(R.id.button);  
  11.         button.setOnClickListener( new  View.OnClickListener()   
  12.         {  
  13.    @Override  
  14.    public  void  onClick(View v)   
  15.    {  
  16.     Intent intent =  new  Intent();  
  17.     intent.setAction( "com.hoo.kay" );  
  18.     //設置數據URI與數據類型匹配  
  19.     //intent.setData(data);  
  20.     //intent.setType(type);注意這個方法會清除setData的內容,所以如果既要設置類型與數據,那麼使用setDataAndType  
  21.     intent.setDataAndType(Uri.parse( "hoo://www.hoo.com/person" ),  "image/gif" );  
  22.     startActivity(intent);  
  23.    }  
  24.   });  
  25.     }  
  26. }</strong></span></span>  


注意上面隱式意圖設置匹配規則的方法,intent.setType(type);注意這個方法會清除setData的內容,所以如果既要設置類型與數據,那麼使用setDataAndType


  1. span  style "background-color: rgb(255, 255, 255);" span  style "font-size:18px;" strong application  android:icon "@drawable/icon"  android: label "@string/app_name" >  
  2.         activity  android:name ".MainActivity"  
  3.                   android:label "@string/app_name" >  
  4.             intent-filter >  
  5.                 action  android:name "android.intent.action.MAIN"  />  
  6.                 category  android:name "android.intent.category.LAUNCHER"  />  
  7.             </ intent-filter >  
  8.         </ activity >  
  9.   activity  android:name ".OtherActivity"   android:label "@string/app_name">  
  10.             intent-filter >  
  11.                 action  android:name "com.hoo.kay"  />  
  12.                 action  android:name "com.hoo.kesen"  />  
  13.                 category  android:name "android.intent.category.DEFAULT"  />  
  14.                 category  android:name "com.hoo.category.li"  />  
  15.                 data  android:scheme "hoo"  android:host "www.hoo.com" android:path "/person" />  
  16.                 data  android:mimeType "image/gif" />  
  17.             </ intent-filter >  
  18.         </ activity >  
  19.     </ application </ strong </ span </ span >  

沒有留言:

張貼留言