Android 包括四大組件,activity、service、broadcast、contentprovider。四大組件依靠intent 緊密聯繫在一起。所以有必要先學習一下intent。
簡介
什麼是intent,按照文檔解釋:An intent is an abstract description of anoperation to be performed。翻譯過來就是:intent 是對將要執行的動作的一個抽象描述。
Intent可以用來做什麼?
1. 啓動一個activity。可以通過Context.startActivity(intent)或者startactivityforResult來啓動一個activity,且這個intent可以攜帶一些必要的數據。
2. 啓動一個service。可以通過Context.startService(intent)來啓動一個servie。或者如果service被設計爲一個C-S的接口,那麼可以通過bindService(intent)綁定到這個service。
3. 發送廣播。可以通過發送廣播,通知某些事件的發生,如系統啓動等。通過傳一個Intent到方法sendBroadcast(),sendOrderedBroadcast(), 或者sendStickyBroadcast().來發送廣播。
Intent 分類
有兩種類型的intent。分別是明確的(Explicit)和非明確(Implicit)的。
1. 明確的intent.通過完整的限定類名來描述intent。通常使用明確的intent來啓動你自己的app中的一個組件,因爲你清楚的知道其類名。如new inent(this,TestActivirty.class),Context.startActivity(intent);
2. 非明確的intent。沒有提供精確的類名,但是聲明瞭將要執行的動作(Action)以及其他數據,如Category 和data。
當使用明確的Intent來啓動一個activity或者service的時候,系統可以立刻啓動相應的組件,並把這個intent傳遞給他。當使用非明確的intent的時候,系統爲了找到合適的組件,需要掃描manifest 文件來尋找合適的組件。這是通過匹配intent Filter 進行的。
構建intent.
Intent 包含了很多信息,android系統使用這些信息來決定啓動哪些組件。主要包含以下信息:組件名稱(component name)、動作(action)、數據(data)、策略(category)。
1. 組件名稱
待要啓動的組件的名稱。這是一個可選的信息,但是它是構造明確的intent所必須需要的信息。當啓動一個service的時候,儘可能的使用明確的intent,否則很可能有意想不到的結果。可以如下構建一個intent:
//直接構造函數構造 Intent intent = new Intent(this, MainActivity.class);
Intent intent1 = new Intent(); //通過以下三個方法構造 intent1.setComponent(new ComponentName(packageName, className)); intent1.setClass(this, MainActivity.class); intent1.setClassName(this, MainActivity.class.getCanonicalName()); |
2. 動作
一個String,代表將要執行的動作。如選擇或者查看、編輯。Action通常決定了intent的剩餘的部門怎麼構造,如它應該包含哪些data和extras。系統預定義了一些Action,儘可能的使用它們,你也可以定義自己的action
3. 數據
Data 包含兩方面的信息,URI和MIME type。前者表示數據的地址,後者表示數據的類型。有的時候URI暗含有MIME,例如contentProvider, Conten:URI.
單獨設置URI,使用方法setData,單獨設置MIME,使用setType。如果都要設置,那麼使用setDataAndType。建議使用最後一個,因爲單獨使用的時候,會把另外一個置爲null.
4. 策略
額爲信息,它說明了可以處理這個intent的組件類型。一個intent可以有任意數量的category,但是並不是必須。
CATEGORY_BROWSABLE :這個activity 允許自己被一個web瀏覽器啓動來顯示被一個鏈接引用的數據,如一張圖片或者一個email。
Intent也可以附帶那些不影響解析,啓動哪一個組件的信息,如extras和flag。
5. 額外信息
這是完全自己定義的,用來向下一個組件傳遞信息。
6. Flag
這是與task有關的變量,它影響了activity在task棧中的存在方式。
Intent注意
當 調用stattActivity(intent)的時候,如果intent 不能被解析爲一個activity,那麼就會拋出異常而程序崩潰,爲了防止這種情況,可以做以下處理
Intent intent1 = new Intent(); if (intent.resolveActivity(getPackageManager())!=null) { startActivity(intent); } |
當使用非明確的intent的時候,對於一個intent,可能有多個app的組件都可以響應,這個時候系統會彈出一個選擇列表供用戶選擇。
當然這個選擇框,也可以自定義標題。如下:
Intent intent1 = new Intent(); Intent chooseIntent = Intent.createChooser(intent1, "請自定義選擇的標題"); if (intent1.resolveActivity(getPackageManager())!=null) { startActivity(chooseIntent); } |
接收intent 和intent Filter
對於明確的intent,總是被髮送給它確切的目標組件,而不管這個組件聲明的intent filter。
對於非明確的intent,那就需要根據在android manifest 中聲明的intent filter按照一定的規則進行匹配。每一個intent filter 都基於 Action、data和category 描述了其所能接收的intent。
下面是filter的例子,一個組件可以有多個intent filter:
<activity android:name="MainActivity"> <!-- This activity is the main entry, should appear in app launcher --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
<activity android:name="ShareActivity"> <!-- This activity handles "SEND" actions with text data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <action android:name="android.intent.action.SEND_MULTIPLE"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="application/vnd.google.panorama360+jpg"/> <data android:mimeType="image/*"/> <data android:mimeType="video/*"/> </intent-filter> </activity> |
Intent解析
一個非明確的intent 需要通過intent filter 的檢測,纔可以發送到通過檢測的組件,這個檢測對於intent filter 的 action、data和category。
Action測試。一個filter中可以有0個或者多個action屬性。Intent需要匹配其中的一個,纔可以通過測試。如果filter中沒有action,那麼intent測試不通過,除非這個intent沒有添加action的描述。
Category測試。一個filter中可以有0個或者多個category。Intent也可以添加多個category。需要添加的每個category都能匹配filter 中的某個,纔可以測試通過。因此,當一個intent中沒有任何category中,總是可以測試通過。注意,android自動的爲每一個隱含的intent(用來調用startActivity 或者startactivityforesult)添加CATEGORY_DEFAULT
這個category。所以activityz必須在androidmanefest文件中其對應的filter中添加此category,課可以接收非明確的intent。
Data測試。Mime type的匹配和 scheme://host:port/pathor pathPrefix or pathPattern 的匹配。類似以上。
DevGuide http://developer.android.com/guide/topics/manifest/data-element.html