3、顯式Intent小結
有兩種方式來顯示的指示要啓動的Activity:
方式一:(通過setClassName)
- Intent intent = new Intent();
- //表示希望啓動com.example.test_permission包中的com.example.test_permission.MainActivity
- intent.setClassName("com.example.test_permission", "com.example.test_permission.MainActivity");
- startActivity(intent);
- Intent intent = new Intent();
- intent.setClass(Context packageContext, OtherActivity.class);
- 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,一般都能看到一段代碼,舉個例子,我隨便複製一個,如下:
- <activity
- android:name=".MainActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
在這個標籤裏定義的所有東東都是用來定義該activity可以被哪些intent激活的,如果匹配,就會被激活!!!!!
在<intent-filter>裏有以下幾個屬性可以讓intent來匹配:Action、Category、Data;下面逐一介紹:
1、Action:該activity可以執行的動作
該標識用來說明這個activity可以執行哪些動作,所以當隱式intent傳遞過來action時,如果跟這裏<intent-filter>所列出的任意一個匹配的話,就說明這個activity是可以完成這個intent的意圖的,可以將它激活!!!!
常用的Action如下所示:
- ACTION_CALL activity 啓動一個電話.
- ACTION_EDIT activity 顯示用戶編輯的數據.
- ACTION_MAIN activity 作爲Task中第一個Activity啓動
- ACTION_SYNC activity 同步手機與數據服務器上的數據.
- ACTION_BATTERY_LOW broadcast receiver 電池電量過低警告.
- ACTION_HEADSET_PLUG broadcast receiver 插拔耳機警告
- ACTION_SCREEN_ON broadcast receiver 屏幕變亮警告.
- 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屬性如下所示:
- CATEGORY_DEFAULT:Android系統中默認的執行方式,按照普通Activity的執行方式執行。表示所有intent都可以激活它
- CATEGORY_HOME:設置該組件爲Home Activity。
- CATEGORY_PREFERENCE:設置該組件爲Preference。
- CATEGORY_LAUNCHER:設置該組件爲在當前應用程序啓動器中優先級最高的Activity,通常爲入口ACTION_MAIN配合使用。
- CATEGORY_BROWSABLE:設置該組件可以使用瀏覽器啓動。表示該activity只能用來瀏覽網頁。
- 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域應該是這樣的:
- <activity android:name=".TargetActivity">
- <intent-filter>
- <action android:name="com.scott.intent.action.TARGET"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:scheme="scott" android:host="com.scott.intent.data" android:port="7788" android:path="/target"/>
- </intent-filter>
- </activity>
這個標識比較特殊,它定義了執行此Activity時所需要的數據,也就是說,這些數據是必須的!!!!!所有如果其它條件都足以激活該Activity,但intent卻沒有傳進來指定類型的Data時,就不能激活該activity!!!!
三、Intent隱式傳遞方法
上面我們講了一個Activity能被某隱式Intent喚醒的原則,只有這些全部匹配的intent才能喚醒這個Activity,下面我們就講講怎麼向隱式intent傳遞這些參數,以便與activity匹配將向喚醒。
1、Action
使用Intent的一個構造方法即可實現傳遞Action參數:
- public Intent(String action) {
- mAction = action;
- }
- <activity android:name=".TargetActivity">
- <intent-filter>
- <action android:name="com.scott.intent.action.TARGET"/>
- <category android:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- </activity>
- public void gotoTargetActivity(View view) {
- Intent intent = new Intent("com.scott.intent.action.TARGET");
- startActivity(intent);
- }
注意這裏再次提醒,一個activity可以有多個action,只要有一個匹配就可以被啓動。同樣,如果僅指定某個action,而多個activity都具有這個action的話,系統會列出列表供用戶選擇執行哪一個activity.
2、Category
一個intent對象可以有任意個category。intent類定義了許多category常數.- addCategory()方法爲一個intent對象增加一個category,
- removeCategory刪除一個category,
- getCategories()獲取intent所有的category.
3、Data
有兩種傳遞data的方式:
第一種:利用構造函數:
- public Intent(String action, Uri uri) {
- mAction = action;
- mData = uri;
- }
- Intent intent = new Intent("com.scott.intent.action.name");
- intent.setData(Uri.parse("scheme://host:port/parth"));
- startActivity(intent);
- <activity android:name=".TargetActivity">
- <intent-filter>
- <action android:name="com.scott.intent.action.TARGET"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:scheme="scott" android:host="com.scott.intent.data" android:port="7788" android:path="/target"/>
- </intent-filter>
- </activity>
- Intent intent = new Intent("com.scott.intent.action.TARGET");
- intent.setData(Uri.parse("scott://com.scott.intent.data:7788/target"));
- startActivity(intent);
注意:
不過有時候對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對象傳遞
發送方
- Intent intent = new Intent("com.scott.intent.action.TARGET");
- Bundle bundle = new Bundle();
- bundle.putInt("id", 0);
- bundle.putString("name", "scott");
- intent.putExtras(bundle);
- startActivity(intent);
- Bundle bundle = intent.getExtras();
- int id = bundle.getInt("id");
- String name = bundle.getString("name");
更多參數傳遞方法見《通過Intent傳遞類對象》
5、附《Intent調用常見系統組件方法》
- // 調用瀏覽器
- Uri webViewUri = Uri.parse("http://blog.csdn.net/zuolongsnail");
- Intent intent = new Intent(Intent.ACTION_VIEW, webViewUri);
- // 調用地圖
- Uri mapUri = Uri.parse("geo:100,100");
- Intent intent = new Intent(Intent.ACTION_VIEW, mapUri);
- // 播放mp3
- Uri playUri = Uri.parse("file:///sdcard/test.mp3");
- Intent intent = new Intent(Intent.ACTION_VIEW, playUri);
- intent.setDataAndType(playUri, "audio/mp3");
- // 調用撥打電話
- Uri dialUri = Uri.parse("tel:10086");
- Intent intent = new Intent(Intent.ACTION_DIAL, dialUri);
- // 直接撥打電話,需要加上權限<uses-permission id="android.permission.CALL_PHONE" />
- Uri callUri = Uri.parse("tel:10086");
- Intent intent = new Intent(Intent.ACTION_CALL, callUri);
- // 調用發郵件(這裏要事先配置好的系統Email,否則是調不出發郵件界面的)
- Uri emailUri = Uri.parse("mailto:[email protected]");
- Intent intent = new Intent(Intent.ACTION_SENDTO, emailUri);
- // 直接發郵件
- Intent intent = new Intent(Intent.ACTION_SEND);
- String[] tos = { "[email protected]" };
- String[] ccs = { "[email protected]" };
- intent.putExtra(Intent.EXTRA_EMAIL, tos);
- intent.putExtra(Intent.EXTRA_CC, ccs);
- intent.putExtra(Intent.EXTRA_TEXT, "the email text");
- intent.putExtra(Intent.EXTRA_SUBJECT, "subject");
- intent.setType("text/plain");
- Intent.createChooser(intent, "Choose Email Client");
- // 發短信
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.putExtra("sms_body", "the sms text");
- intent.setType("vnd.android-dir/mms-sms");
- // 直接發短信
- Uri smsToUri = Uri.parse("smsto:10086");
- Intent intent = new Intent(Intent.ACTION_SENDTO, smsToUri);
- intent.putExtra("sms_body", "the sms text");
- // 發彩信
- Uri mmsUri = Uri.parse("content://media/external/images/media/23");
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.putExtra("sms_body", "the sms text");
- intent.putExtra(Intent.EXTRA_STREAM, mmsUri);
- intent.setType("image/png");
- // 卸載應用
- Uri uninstallUri = Uri.fromParts("package", "com.app.test", null);
- Intent intent = new Intent(Intent.ACTION_DELETE, uninstallUri);
- // 安裝應用
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(Uri.fromFile(new File("/sdcard/test.apk"), "application/vnd.android.package-archive");
- // 在Android Market中查找應用
- Uri uri = Uri.parse("market://search?q=憤怒的小鳥");
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);