Android應用程式中三個主要的組件——Activity, Service, Broadcast receiver——都是由Intent中傳遞過來的消息激活的, Intent消息傳遞是這樣一個基礎手段,它把相同或者不同應用程式的組件後期運行綁定起來。Intent對象本身是一個被動的數據結構,它用來承載一個關於將要執行動作的抽象描述——在 broadcast的情況下,這個Intent是描述是已經發生,並且被通知到的執行動作[比方說開機完畢, 需要執行一個操作], 下面有很多相互獨立機制,為每種類型的組件傳遞Intent:
1. 一個Intent 對象傳給Context.startActivity()或者Activity.startActivityForResult() 去啟動一個Activity或者利用已存在的Activity執行某項操作.
2.一個Intent 對象傳給Content.startService(),初始化一個Service或者為一個正在進行的Service傳遞新的指示。同樣地,一個intent對象傳給Context.bindService(),用來建立主動調用的組件和目標Service之間的連接。如果Service尚未運行,則可選擇性的啟動。
3.Intent對象傳遞給任意broadcast方法,如Context.sendBroadcast(), Context.sendOrderBroadCast(),或者Context.sendStickyBroadCast(), 這種方式的傳遞,會將Intent傳遞給所有感興趣的Broadcastreceiver. 許多broadcast起源於系統代碼。
在上述各情況下,Android系統要找到需要的Activity, Service, 或者是broadcast receiver的集合,從而響應intent消息,並且在需要的情況下初始化這些組件。這些Intent消息沒有交集:broadcast intent 只送往broadcast receiver, 不會送往activity或者service. 一個Intent傳給startActivity(), 只會送往activity, 不會送給一個service或者broadcast receiver。
本文檔開篇介紹Intent對象. 然後介紹Android中intent和組件的映射規則——Android如何解決那個組件應該接收一個Intent消息。由於Intent沒有明顯的指明要調用哪個Component, 這個過程包含測試Intent對象和關聯潛在目標組件的Intent filter.
Intent Objects:
一個Intent對象是信息的集合. 它包含需要接收這個Intent的組件感興趣的消息(如產生什麼樣的動作,以及這個動作的數據對象),還包含Android系統需要的附加信息(需要處理 這個Intent的組件分類,以及如何啟動目標Activity), 原則上,一個Intent包含如下信息:
Component Name : 處理這個Intent的組件名稱。 這是一個ComponentName屬性對象——目標組件的類全名(如"com.example.project.app.FreneticActivity")以及在manifest文件中,設置組件Package位 置的信息(如"com.example.project"). 組件名稱的package部分和package的名稱不一定要完全匹配。
組件名稱是可選的, 如果設置了這個組件名稱, Intent對象會發送到指定組件的實例。如果沒有設置,Android利用其它的信息定位和是的組件目標——查看後續章節的 Intent Resolution.
組件的名稱通過setComponent(), setClass(), setClassName()設置,通過getComponent讀取。
Action :它是將要執行動作的字符串名稱——對於Broadcast Intent, 發生的Action不斷上報。 Intent類定義了許多Action 常量,包括下面的:
【這裡是一個表格.後面去移植】
可以查看API,可以發現預先定義的一些Action常量. 其它的一些Actions定義在Android api的其他地方,可以在自己的應用中,自定義可以被組件激活的Action字符串。這些自定義的需要將應用程式的包名作為前綴, 如"com.example.project.SHOW_COLOR".
Action很大程度上決定了Intent的其他部分的組織結構 ——特別是Intent的data和extras屬性——如同一個方法名決定了傳入的參數和返回值。 鑑於上述原因,明智的做法是:儘可能的使用特別的Action名稱,並且和Intent的其他屬性緊緊綁定。換句話說,為你的組件用到的Intent對象 定義一個完整的約定,而不是每個Action無規則的各自定義。
Intent中Action的設置是用setAction(),讀取採用getAction();
Data :指的是操作的數據以及這個數據的MIME類型。不同的Action對應不同的數據說明。 比如,如果Intent的的action屬性為ACTION_EDIT, 則為了顯示並編輯,Intent的data屬性需要包含文檔的URI; 如果Intent的ation屬性為ACTION_CALL, 則Intent的data屬性需要為tel:包含撥打電話的URI. 同樣地, 如果Intent的action域為ACTION_VIEW並且Intent的data域為http:URI, 接收Intent的Activity將被調用並且下載和現實這個URI表示的資源。
當匹配一個Intent到一個組件,並且能夠處理數據時,除了了解URI外,獲知這個數據的MIME類型是很重要的。比如,一個能打開圖像文件的組件,不應該用來播放音頻文件。
在很多情況下,可以從URI推斷出data的類型——特別是content:URIs,它表示數據位於設備中,並且有一個content provider控制(查看separate discussion on consten providers). 但是,數據類型同樣可以顯示的在Intent對象找哦你個設置. setData()方法僅僅設置數據的URI, setType()方法僅僅設置數據的MIMIE類型,setDataAndType()同時設定URI和MIME類型。通過getData()取URI,通過getType()取MIME類型
Category :指的是一個包含附加信息的String,附加信息是關於應該處理Intent的組件類型。任意數目的category描述都可以防止到一個Intent 對象中. 跟Action的做法類似,intent類也定義了多個catagory常量,如:
【這是一個表....稍後去遷移】
查API文檔中的Intent, 可以獲得所有Category列表.addCategory()方法將一個Category設置到Intent對象中。removeCategory() 刪除一個之前設置的Category. getCategoryies()方法得到當前Intent對象中所有的categories.
Extras : 指的是一個Key-Value對,用來給目標組件傳遞附加信息,正如某些Action和特定的數據URI一樣的對應關係,存在某些特殊的extras, 比如: 一個ACTION_TIMEZONE_CHANGED intent有一個"time-zone" extra定義了一個新時區,ACTION_HEADSET_PLUG 有一個"state" extra 表明耳機是否插上還是拔出,而"name" extra則表明了耳機的類型. 如果你需要實現一個SHOW_COLOR action, color的值需要在extra的key-value對中被設置好。
Intent對象中有一系列的putXXX()方法,可以插入不同種類的extra 數據,同樣有一系列getXXX()方法用來讀取數據. 這些方法對Bundle對象而言都是平行的. 事實上,這些extras可以用Bundle的形式,通過putExtras()和getExtras()方法插入和存取。
Flags :指的是各種各樣的標誌。大多數用來告知Android系統如何啟動一個Activity(如Activity屬於哪個task),如何在啟動之後處理這個Activity(如Activity是否在最近的Activities集合中). 所有的這些標誌都定義在Intent類中。
Android系統和它所帶的應用程式利用Intent對象, 發送系統產生的broadcast並且激活系統定義的component. 想諒解如何結構化一個Intent對象,並激活系統組件,參考:list of intents.
1. Intent和Activity關聯關係
通過傳遞的Intent來決定Activity的啟動。Intent和Activity的關係是一對多,比如,傳遞一個Type為mp3的Intent,可能會讓你選
擇多個Activity——Android自帶的音樂播放或者你自己選擇的播放器等。Activity在AndroidManifest.xml中預先定義了與哪個Intent相
關,這樣方便後面傳遞Intent,即可以激活對應的Activity。
2. Intent 和 Activity的全局性.
無疑可以自定義Activity的Intent-Filter,這樣每個應用(可以稱為進程嗎?)自己搞定自己的事情就OK, 但為了應用之間通信
的方便, 比如,系統已經有了一個音樂播放器Activity,何必自己再實現? 因此只需要構造能讓該播放器Activity識別的Intent就
行了。 因此通過一些全局的變量塑造Intent,就實現了Activity的復用。方式是利用Intent中的全局常量,如
Intent.ACTION_MAIN,Intent.CATEGORY_SAMPLE_CODE等,定義到Acitity中,這樣大家都能使用這樣的Activity了。
簡單示例:
private void testPM() { Intent mainIntent = new Intent("com.ostrichmyself.xxx", null); PackageManager pm = getPackageManager(); List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0); for (int i = 0; i < list.size(); i++) { ResolveInfo info = list.get(i); Log.i("Test Intent---", info.activityInfo.name); } } AndroidManifest.xml中定義為: <activity android:name=".MyActivity" android:label="myActivity"> <intent-filter> <action android:name="com.ostrichmyself.xxx" /> </intent-filter> </activity>注意TestPM()這段代碼可以放在和MyActivity所在的application中,也可以放在其它地方。 原因是Activity是全局的。
原文連結:
http://blog.csdn.net/ostrichmyself/article/details/5667301