intent詳解

3、顯式Intent小結

有兩種方式來顯示的指示要啓動的Activity:

方式一:(通過setClassName)

[java] view plain copy
  1. Intent intent = new Intent();  
  2. //表示希望啓動com.example.test_permission包中的com.example.test_permission.MainActivity  
  3. intent.setClassName("com.example.test_permission""com.example.test_permission.MainActivity");  
  4. startActivity(intent);  


方式二:(通過SetClass)
[java] view plain copy
  1. Intent intent = new Intent();  
  2. intent.setClass(Context packageContext, OtherActivity.class);  
  3. startActivity(intent);  

同樣,setClass(Context packageContext, OtherActivity.class);是指啓動packageContext包裏的OtherActivity.class類;


二、針對隱式intent,Activity的匹配原則

上面我們講了隱式intent是要靠系統自動去匹配並啓動某個activity的。那系統是怎樣匹配activity的呢,系統是怎樣知道這個actitiy就是某個intent想要的呢。

某個activity能不能被某個intent激活,要看這個activity是不是符合這個intent的要求,而某個activity能被哪個intent激活是有定義的,定義就在AndroidManifest.xml

打開AndroidManifest.xml,找到任意一個activity,一般都能看到一段代碼,舉個例子,我隨便複製一個,如下:

[html] view plain copy
  1. <activity  
  2.     android:name=".MainActivity"  
  3.     android:label="@string/app_name" >  
  4.     <intent-filter>  
  5.         <action android:name="android.intent.action.MAIN" />  
  6.   
  7.         <category android:name="android.intent.category.LAUNCHER" />  
  8.     </intent-filter>  
  9. </activity>  
看這裏有一對標籤<intent-filter>……</intent-filter>
在這個標籤裏定義的所有東東都是用來定義該activity可以被哪些intent激活的,如果匹配,就會被激活!!!!!

在<intent-filter>裏有以下幾個屬性可以讓intent來匹配:Action、Category、Data;下面逐一介紹:

1、Action:該activity可以執行的動作

該標識用來說明這個activity可以執行哪些動作,所以當隱式intent傳遞過來action時,如果跟這裏<intent-filter>所列出的任意一個匹配的話,就說明這個activity是可以完成這個intent的意圖的,可以將它激活!!!!

常用的Action如下所示:

[html] view plain copy
  1. ACTION_CALL activity 啓動一個電話.  
  2. ACTION_EDIT activity 顯示用戶編輯的數據.  
  3. ACTION_MAIN activity 作爲Task中第一個Activity啓動  
  4. ACTION_SYNC activity 同步手機與數據服務器上的數據.  
  5. ACTION_BATTERY_LOW broadcast receiver 電池電量過低警告.  
  6. ACTION_HEADSET_PLUG broadcast receiver 插拔耳機警告  
  7. ACTION_SCREEN_ON broadcast receiver 屏幕變亮警告.  
  8. ACTION_TIMEZONE_CHANGED broadcast receiver 改變時區警告.  
兩條原則:

  • 一條<intent-filter>元素至少應該包含一個<action>,否則任何Intent請求都不能和該<intent-filter>匹配。
  • 如果Intent請求的Action和<intent-filter>中個任意一條<action>匹配,那麼該Intent就可以激活該activity(前提是除了action的其它項也要通過)
兩條注意:

如果Intent請求或<intent-filter>中沒有說明具體的Action類型,那麼會出現下面兩種情況。

  •  如果<intent-filter>中沒有包含任何Action類型,那麼無論什麼Intent請求都無法和這條<intent-filter>匹配。
  •  反之,如果Intent請求中沒有設定Action類型,那麼只要<intent-filter>中包含有Action類型,這個Intent請求就將順利地通過<intent-filter>的行爲測試。

2、Category:於指定當前動作(Action)被執行的環境

即這個activity在哪個環境中才能被激活。不屬於這個環境的,不能被激活。

常用的Category屬性如下所示:

[html] view plain copy
  1.  CATEGORY_DEFAULT:Android系統中默認的執行方式,按照普通Activity的執行方式執行。表示所有intent都可以激活它   
  2.   
  3. CATEGORY_HOME:設置該組件爲Home Activity。  
  4.   
  5. CATEGORY_PREFERENCE:設置該組件爲Preference。   
  6.   
  7. CATEGORY_LAUNCHER:設置該組件爲在當前應用程序啓動器中優先級最高的Activity,通常爲入口ACTION_MAIN配合使用。   
  8.   
  9. CATEGORY_BROWSABLE:設置該組件可以使用瀏覽器啓動。表示該activity只能用來瀏覽網頁。   
  10.   
  11. CATEGORY_GADGET:設置該組件可以內嵌到另外的Activity中。  
注意:

如果該activity想要通過隱式intent方式激活,那麼不能沒有任何category設置,至少包含一個android.intent.category.DEFAULT

3、Data  執行時要操作的數據

在目標<data/>標籤中包含了以下幾種子元素,他們定義了url的匹配規則:

  • android:scheme 匹配url中的前綴,除了“http”、“https”、“tel”...之外,我們可以定義自己的前綴
  • android:host 匹配url中的主機名部分,如“google.com”,如果定義爲“*”則表示任意主機名
  • android:port 匹配url中的端口
  • android:path 匹配url中的路徑

在XML中聲明可以操作的data域應該是這樣的:

[html] view plain copy
  1. <activity android:name=".TargetActivity">  
  2. <intent-filter>  
  3.     <action android:name="com.scott.intent.action.TARGET"/>  
  4.     <category android:name="android.intent.category.DEFAULT"/>  
  5.     <data android:scheme="scott" android:host="com.scott.intent.data" android:port="7788" android:path="/target"/>  
  6. </intent-filter>  
  7. </activity>  
注意:

這個標識比較特殊,它定義了執行此Activity時所需要的數據,也就是說,這些數據是必須的!!!!!所有如果其它條件都足以激活該Activity,但intent卻沒有傳進來指定類型的Data時,就不能激活該activity!!!!

三、Intent隱式傳遞方法

上面我們講了一個Activity能被某隱式Intent喚醒的原則,只有這些全部匹配的intent才能喚醒這個Activity,下面我們就講講怎麼向隱式intent傳遞這些參數,以便與activity匹配將向喚醒。

1、Action

使用Intent的一個構造方法即可實現傳遞Action參數:

[java] view plain copy
  1. public Intent(String action) {  
  2.     mAction = action;  
  3. }  
對於有如下聲明的Activity:
[html] view plain copy
  1. <activity android:name=".TargetActivity">  
  2.     <intent-filter>  
  3.         <action android:name="com.scott.intent.action.TARGET"/>   
  4.         <category android:name="android.intent.category.DEFAULT"/>  
  5.     </intent-filter>  
  6. </activity>  
要激活這個Activity,就需要如下這樣構造Intent:(直接向intent中傳遞action的name值)

[java] view plain copy
  1. public void gotoTargetActivity(View view) {  
  2.     Intent intent = new Intent("com.scott.intent.action.TARGET");  
  3.     startActivity(intent);  
  4. }  
這樣就可以啓動我們上面的這個activity了。

注意這裏再次提醒,一個activity可以有多個action,只要有一個匹配就可以被啓動。同樣,如果僅指定某個action,而多個activity都具有這個action的話,系統會列出列表供用戶選擇執行哪一個activity.

2、Category

一個intent對象可以有任意個category。intent類定義了許多category常數.
  • addCategory()方法爲一個intent對象增加一個category,
  • removeCategory刪除一個category,
  • getCategories()獲取intent所有的category.

3、Data

有兩種傳遞data的方式:

第一種:利用構造函數:

[java] view plain copy
  1. public Intent(String action, Uri uri) {  
  2.     mAction = action;  
  3.     mData = uri;  
  4. }  
第二種:利用Intent::SetData(URI uri)
[java] view plain copy
  1. Intent intent = new Intent("com.scott.intent.action.name");  
  2. intent.setData(Uri.parse("scheme://host:port/parth"));  
  3. startActivity(intent);  
舉個例子:(改動下上面的action的例子)

[html] view plain copy
  1. <activity android:name=".TargetActivity">  
  2.     <intent-filter>  
  3.         <action android:name="com.scott.intent.action.TARGET"/>  
  4.         <category android:name="android.intent.category.DEFAULT"/>  
  5.         <data android:scheme="scott" android:host="com.scott.intent.data" android:port="7788" android:path="/target"/>  
  6.     </intent-filter>  
  7. </activity>  
這個時候如果要啓動這個TargetActivity只指定action就不夠了,我們需要爲其設置data值,如下:

[java] view plain copy
  1. Intent intent = new Intent("com.scott.intent.action.TARGET");  
  2. intent.setData(Uri.parse("scott://com.scott.intent.data:7788/target"));  
  3. startActivity(intent);  
此時,url中的每個部分和TargetActivity配置信息中全部一致才能跳轉成功,否則就被系統拒絕。

注意:

不過有時候對path限定死了也不太好,比如我們有這樣的url:(scott://com.scott.intent.data:7788/target/hello)(scott://com.scott.intent.data:7788/target/hi)

這個時候該怎麼辦呢?我們需要使用另外一個元素:android:pathPrefix,表示路徑前綴。
我們把android:path="/target"修改爲android:pathPrefix="/target",然後就可以滿足以上的要求了。

4、Extras

這個參數不參與匹配activity,而僅作爲額外數據傳送到另一個activity中,接收的activity可以將其取出來。這些信息並不是激活這個activity所必須的。也就是說激活某個activity與否只上action、data、catagory有關,與extras無關。而extras用來傳遞附加信息,諸如用戶名,用戶密碼什麼的。

可通過putXX()和getXX()方法存取信息;也可以通過創建Bundle對象,再通過putExtras()和getExtras()方法來存取。 

通過bundle對象傳遞

發送方

[java] view plain copy
  1. Intent intent = new Intent("com.scott.intent.action.TARGET");    
  2. Bundle bundle = new Bundle();    
  3. bundle.putInt("id"0);    
  4. bundle.putString("name""scott");    
  5. intent.putExtras(bundle);    
  6. startActivity(intent);    
接收方:

[java] view plain copy
  1. Bundle bundle = intent.getExtras();  
  2. int id = bundle.getInt("id");  
  3. String name = bundle.getString("name");  


更多參數傳遞方法見《通過Intent傳遞類對象》


5、附《Intent調用常見系統組件方法》

[java] view plain copy
  1. // 調用瀏覽器  
  2. Uri webViewUri = Uri.parse("http://blog.csdn.net/zuolongsnail");  
  3. Intent intent = new Intent(Intent.ACTION_VIEW, webViewUri);  
  4.   
  5. // 調用地圖  
  6. Uri mapUri = Uri.parse("geo:100,100");  
  7. Intent intent = new Intent(Intent.ACTION_VIEW, mapUri);  
  8.   
  9. // 播放mp3  
  10. Uri playUri = Uri.parse("file:///sdcard/test.mp3");  
  11. Intent intent = new Intent(Intent.ACTION_VIEW, playUri);  
  12. intent.setDataAndType(playUri, "audio/mp3");  
  13.   
  14. // 調用撥打電話  
  15. Uri dialUri = Uri.parse("tel:10086");  
  16. Intent intent = new Intent(Intent.ACTION_DIAL, dialUri);  
  17. // 直接撥打電話,需要加上權限<uses-permission id="android.permission.CALL_PHONE" />  
  18. Uri callUri = Uri.parse("tel:10086");  
  19. Intent intent = new Intent(Intent.ACTION_CALL, callUri);  
  20.   
  21. // 調用發郵件(這裏要事先配置好的系統Email,否則是調不出發郵件界面的)  
  22. Uri emailUri = Uri.parse("mailto:[email protected]");  
  23. Intent intent = new Intent(Intent.ACTION_SENDTO, emailUri);  
  24. // 直接發郵件  
  25. Intent intent = new Intent(Intent.ACTION_SEND);  
  26. String[] tos = { "[email protected]" };  
  27. String[] ccs = { "[email protected]" };  
  28. intent.putExtra(Intent.EXTRA_EMAIL, tos);  
  29. intent.putExtra(Intent.EXTRA_CC, ccs);  
  30. intent.putExtra(Intent.EXTRA_TEXT, "the email text");  
  31. intent.putExtra(Intent.EXTRA_SUBJECT, "subject");  
  32. intent.setType("text/plain");  
  33. Intent.createChooser(intent, "Choose Email Client");  
  34.   
  35. // 發短信  
  36. Intent intent = new Intent(Intent.ACTION_VIEW);  
  37. intent.putExtra("sms_body""the sms text");  
  38. intent.setType("vnd.android-dir/mms-sms");  
  39. // 直接發短信  
  40. Uri smsToUri = Uri.parse("smsto:10086");  
  41. Intent intent = new Intent(Intent.ACTION_SENDTO, smsToUri);  
  42. intent.putExtra("sms_body""the sms text");  
  43. // 發彩信  
  44. Uri mmsUri = Uri.parse("content://media/external/images/media/23");  
  45. Intent intent = new Intent(Intent.ACTION_SEND);  
  46. intent.putExtra("sms_body""the sms text");  
  47. intent.putExtra(Intent.EXTRA_STREAM, mmsUri);  
  48. intent.setType("image/png");  
  49.   
  50. // 卸載應用  
  51. Uri uninstallUri = Uri.fromParts("package""com.app.test"null);  
  52. Intent intent = new Intent(Intent.ACTION_DELETE, uninstallUri);  
  53. // 安裝應用  
  54. Intent intent = new Intent(Intent.ACTION_VIEW);  
  55. intent.setDataAndType(Uri.fromFile(new File("/sdcard/test.apk"), "application/vnd.android.package-archive");  
  56.   
  57. // 在Android Market中查找應用  
  58. Uri uri = Uri.parse("market://search?q=憤怒的小鳥");           
  59. Intent intent = new Intent(Intent.ACTION_VIEW, uri);  





發佈了24 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章