天天看點

android四大元件之intent

什麼是Intent

Intent是一種運作時綁定(run-time binding)機制,它能在程式運作過程中連接配接兩個不同的元件。通過Intent,你的程式可以向Android表達某種請求或者意願,Android會根據意願的内容選擇适當的元件來完成請求。比如,有一個Activity希望打開網頁浏覽器檢視某一網頁的内容,那麼這個Activity隻需要發出WEB_SEARCH_ACTION給Android,Android就會根據Intent的請求内容,查詢各元件注冊時聲明的IntentFilter,找到網頁浏覽器的Activity來浏覽網頁。

Android的三個基本元件——Activity,Service和Broadcast Receiver——都是通過Intent機制激活的,不同類型的元件有不同的傳遞Intent方式:

  • 要激活一個新的Activity,或者讓一個現有的Activity做新的操作,可以通過調用Context.startActivity()或者Activity.startActivityForResult()方法。
  • 要啟動一個新的Service,或者向一個已有的Service傳遞新的指令,調用Context.startService()方法或者調用Context.bindService()方法将調用此方法的上下文對象與Service綁定。
  • Context.sendBroadcast()、Context.sendOrderBroadcast()、Context.sendStickBroadcast()這三個方法可以發送Broadcast Intent。發送之後,所有已注冊的并且擁有與之相比對IntentFilter的BroadcastReceiver就會被激活。

Intent一旦發出,Android都會準确找到相比對的一個或多個Activity,Service或者BroadcastReceiver作響應。是以,不同類型的Intent消息不會出現重疊,即Broadcast的Intent消息隻會發送給BroadcastReceiver,而決不會發送給Activity或者Service。由startActivity()傳遞的消息也隻會發給Activity,由startService()傳遞的Intent隻會發送給Service。

Intent的構成

要在不同的activity之間傳遞資料,就要在intent中包含相應的内容,一般來說資料中最基本的應該包括:

  • Action:用來指明要實施的動作是什麼,比如說ACTION_VIEW, ACTION_EDIT等。具體的可以查閱android SDK-> reference中的Android.content.intent類,裡面的constants中定義了所有的action。

    一些常用的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 改變時區警告.

  • Data: 要事實的具體的資料,一般由一個Uri變量來表示

    簡單的Action,Data的例子: 

Uri uri = Uri.parse("http://www.google.com");
Intent it = new Intent(Intent.ACTION_VIEW, uri); 
startActivity(it);
           
  • Category:一個字元串,包含了關于處理該intent的元件的種類的資訊。一個intent對象可以有任意個category。intent類定義了許多category常數:

    CATEGORY_BROWSABLE     目标activity可以使用浏覽器來顯示-例如圖檔或電子郵件消息

    CATEGORY_GADGET             該activity可以被包含在另外一個裝載小工具的activity中

    CATEGORY_HOME                  該activity顯示主螢幕,也就是使用者按下Home鍵看到的界面

    CATEGORY_LAUNCHER        該activity可以作為一個Task的第一個activity,并且列在應用程式啟動器中

    CATEGORY_PREFERENCE   該activity是一個選項面闆

    addCategory()方法為一個intent對象增加一個category,

    removeCategory删除一個category,

    getCategories()擷取intent所有的category.

  • Type:顯式指定Intent的資料類型(MIME)(多用途網際網路郵件擴充,Multipurpose Internet Mail Extensions)。比如,一個元件是可以顯示圖檔資料的而不能播放聲音檔案。很多情況下,data類型可在URI中找到,比如content:開頭的URI,表明資料由裝置上的content provider提供。但是通過設定這個屬性,可以強制采用顯式指定的類型而不再進行推導。
  • component:指定Intent的目标元件的類名稱。通常 Android會根據Intent 中包含的其它屬性的資訊,比如action、data/type、category進行查找,最終找到一個與之比對的目标元件。但是,如果 component這個屬性有指定的話,将直接使用它指定的元件,而不再執行上述查找過程。指定了這個屬性以後,Intent的其它所有屬性都是可選的。例如:
Intent it = new Intent(Activity.Main.this, Activity2.class); 
startActivity(it);
           
  • extras:附加資訊,例如ACTION_TIMEZONE_CHANGED的intent有一個"time-zone"附加資訊來指明新的時區,而ACTION_HEADSET_PLUG有一個“state”附加資訊來訓示耳機是被插入還是被拔出。intent對象有一系列put...()和set...()方法來設定和擷取附加資訊。 這些方法和Bundle對象很像。事實上附加資訊可以使用putExtras()和getExtras()作為Bundle來讀和寫。例如:
//用Bundle傳遞資料 
Intent it = new Intent(Activity.Main.this, Activity2.class); 
Bundle bundle=new Bundle(); 
bundle.putString("name", "This is from MainActivity!"); it.putExtras(bundle); 
startActivity(it);
 //獲得資料 
Bundle bundle=getIntent().getExtras(); 
String name=bundle.getString("name");
           

intent的解析

在應用中,我們可以以兩種形式來使用Intent:

  • 直接Intent(或名顯示intent):指定了component屬性的Intent(調用setComponent(ComponentName)或者setClass(Context, Class)來指定)。通過指定具體的元件類,通知應用啟動對應的元件。
  • 間接Intent(或名隐式intent):沒有指定comonent屬性的Intent。這些Intent需要包含足夠的資訊,這樣系統才能根據這些資訊,在在所有的可用元件中,确定滿足此Intent的元件。

對于直接Intent,Android不需要去做解析,因為目标元件已經很明确,Android需要解析的是那些間接Intent,通過解析将 Intent映射給可以處理此Intent的Activity、Service或Broadcast Receiver。

Intent解析機制主要是通過查找已注冊在AndroidManifest.xml中的所有<intent-filter>及其中定義的Intent,通過PackageManager(注:PackageManager能夠得到目前裝置上所安裝的

application package的資訊)來查找能處理這個Intent的component。在這個解析過程中,Android是通過Intent的action、type、category這三個屬性來進行判斷的,判斷方法如下:

  • 如果Intent指明定了action,則目标元件的IntentFilter的action清單中就必須包含有這個action,否則不能比對;
  • 如果Intent沒有提供type,系統将從data中得到資料類型。和action一樣,目标元件的資料類型清單中必須包含Intent的資料類型,否則不能比對。
  • 如果Intent中的資料不是content:類型的URI,而且Intent也沒有明确指定type,将根據Intent中資料的scheme(比如 http:或者mailto:)進行比對。同上,Intent 的scheme必須出現在目标元件的scheme清單中。
  • 如果Intent指定了一個或多個category,這些類别必須全部出現在組建的類别清單中。比如Intent中包含了兩個類别:LAUNCHER_CATEGORY和ALTERNATIVE_CATEGORY,解析得到的目标元件必須至少包含這兩個類别。