來自 :http://flysnow.iteye.com/blog/961576
在這裏你將會學到:
- 什麼是Intent和Intent Filter
- Intent和Intent Filter有什麼用
- 怎麼啓動(傳遞)一個Intent
- Intent裏包含什麼
- 什麼是顯式Intent以及什麼隱式Intent
- Intent是怎樣匹配的
一:前言
在正式介紹Intent之前,我們先看下上面說的Activity、Service和Broadcast Receiver是怎樣傳遞Intent。對於這三個組件而言,他們都有自己獨立的傳遞Intent的機制:
- Activity:對於Activity來說,它主要是通過Context.startActivity() 或Activity.startActivityForRestult() 來啓動一個存在的Activity做一些事情。當使用Activity.startActivityForResult() 啓動一個Activity時,可以使用Activity.setResult()返回一些結果信息,可以在Activity.onActivityResult() 中得到返回的結果.
- Service:對於Service來說,它主要是通過Context.startService() 初始化一個Service或者傳遞消息給正在運行的Service。同樣,也可以通過Context.bindService() 建立一個調用組件和目標服務之間的連接。
- 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
-
IntentsTestList代碼如下:
- /**
- * Intents測試列表類
- * @author 飛雪無情
- * @since 2011-3-14
- */
- public class IntentsTestList extends ListActivity {
- private String ACTION_VIEW="com.flysnow.intent.ACTION_VIEW";
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //定義ListAdapter
- setListAdapter(new SimpleAdapter(this, getData(),
- android.R.layout.simple_list_item_1, new String[] { "title" },new int[] {android.R.id.text1}));
- getListView().setTextFilterEnabled(true);
- //註冊一個廣播
- super.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Toast.makeText(context, "該Broadcast的Intent Filter值只設置了Action", Toast.LENGTH_SHORT).show();
- }
- },new IntentFilter(ACTION_VIEW));
- }
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- Intent intent=(Intent)getData().get(position).get("intent");
- Boolean isActivity=(Boolean)getData().get(position).get("isActivity");
- if(isActivity){
- startActivity(intent);
- }else{
- sendBroadcast(intent);
- }
- }
- /**
- * 返回ListView需要的數據
- * @return ListView需要的數據
- */
- private List<Map<String,Object>> getData() {
- List<Map<String,Object>> data=new ArrayList<Map<String,Object>>();
- addItem(data, "空Action的Activity", new Intent(),true);
- addItem(data, "Action檢測-Activity", new Intent(ACTION_VIEW),true);
- addItem(data, "Action檢測-Broadcast", new Intent(ACTION_VIEW),false);
- return data;
- }
- /**
- * 給ListView添加數據
- * @param data 存儲數據的List
- * @param name 要顯示的Title
- * @param intent 單擊某一項時要啓動的Activity
- * @param isActivity 啓動的是否是Activity,true是,false爲廣播
- */
- private void addItem(List<Map<String,Object>> data, String name, Intent intent,boolean isActivity) {
- Map<String, Object> temp = new HashMap<String, Object>();
- temp.put("title", name);
- temp.put("intent", intent);
- temp.put("isActivity", isActivity);
- data.add(temp);
- }
- }
-
爲了測試startActivity(),我們新建一個Activity名字爲ActionActivity代碼如下:
- /**
- * @author 飛雪無情
- * @since 2011-3-14
- */
- public class ActionActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- TextView text=new TextView(this);
- text.setText("該Activity的Intent Filter值只設置了Action");
- setContentView(text);
- }
- }
-
AndroidManifest.xml修改如下:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.flysnow.intent"
- android:versionCode="1"
- android:versionName="1.0">
- <uses-sdk android:minSdkVersion="8" />
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".IntentsTestList"
- 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 android:name=".ActionActivity" android:label="Action檢測">
- <intent-filter>
- <action android:name="com.flysnow.intent.ACTION_VIEW"></action>
- <action android:name="android.intent.action.VIEW"></action>
- <category android:name="android.intent.category.DEFAULT"></category>
- </intent-filter>
- </activity>
- </application>
- </manifest>
-
運行入下圖:
當點擊“空Action的Activity”的時候,會報異常,因爲Intent什麼都沒有設置,沒有任何的Activity能處理它 。當點擊“Action檢測-Activity”的時候會打開我們的ActionActivity這個Activity,點擊“Action檢測-Broadcast”會彈出Toast提示,說明已經被接收到。。從上面我們可以看出,當Intent設置了Action時,只要對應的組件的Intent Filter中包含該Action的定義,那麼這個組件就會接收該Intent。。。