Android中的Intent和Intent-Filter詳解(一)
Intent對於Android應用的作用
Intent,翻譯過來是“意圖”,它是對Android應用程式“意圖”的封裝。例如ActivityA想啟動ActivityB,那麼“想啟動ActivityB”就是ActivityA的意圖;ActivityA想啟動ServiceA,“想啟動ServiceA”就是ActivityA的意圖。
至於Android為什麼不直接提供一個類似startActivity(Class activityClass)的方法來移動一個Activity,是因為這樣做會背離Android的設計理念,造成一種硬編碼耦合,不利於高層次的解耦。而Intent提供的程式設計模型,可以讓應用程式只啟動具有某種特徵額元件,不會造成元件(Activity
Intent不僅可以封裝應用程式需要啟動某個元件的“意圖”,還可以作為應用元件之間通訊的重要媒介。例如兩個Activity之間可以通過Bundle物件交換資料,而Intent剛好可以攜帶Bundle物件。
Intent物件如何啟動系統元件
Android應用程式包含三種重要元件:Activity、Service、BroadcastReceiver,應用程式採用了一致的方式來啟動他們——都是依靠Intent來進行啟動的,Intent就封裝了程式想要啟動程式的意圖,不僅如此,Intent還可用於與被啟動元件交換資訊。
下表顯示一部分使用Intent
元件型別 |
啟動方法 |
Activity |
startActivity(Intent i) |
startActivityForResult(Intent intent, int requestCode) |
|
Service |
ComponentName startService(Intent service) |
boolean bindService(Intent service, ServiceConnection conn, int flags) |
|
BroadcastReceiver |
sendBroadcast(Intent intent) |
sendBroadcast(Intent intent, String receiverPermission) |
|
sendOrderedBroadcast(Intent intent, String receiverPermission) |
Intent物件大致包含Component, Action, Category, Data, Type, Extra和Flag這7中屬性,其中Component用於明確指定需要啟動的目標元件,而Extra用於“攜帶”需要交換的資料。下面詳細介紹Intent物件各屬性的作用。
Intent的屬性及Intent-Filter配置
我們知道Intent是用來封裝程式的啟動意圖的,但到底啟動哪個元件,則取決於Intent的各個屬性。
首先舉個例子,有一個女孩兒要找男朋友,此時有兩種方式來表達她的意圖:
-
明確指出要找xxx做她的男朋友,比如找博主我^_^;
-
指出要找“高”、“富”、“帥”做男朋友,至於到底是誰不重要,只要是高富帥就行;
同樣,Intent封裝的意圖與之類似:
-
顯式Intent:通過Component屬性明確指定要啟動哪個元件;
-
隱式Intent:通過Action、Category屬性指出需要啟動符合條件的元件;
Component屬性
該屬性用來明確指定需要啟動哪個元件,其建構函式如下:
-
ComponentName(Stringpkg, String cls):建立pkg所在包下的cls類所對應的元件;
-
ComponentName(Contextpkg, String cls):建立pkg所對應的包下的cls類所對應的元件;
-
ComponentName(Contextpkg, Class<?> cls):建立pkg所對應的包下的cls類所對應的元件;
下面是例子:
ComponentNamecomponentName =newComponentName(getApplicationContext(),ActivityB.class);
Intent intent =newIntent();
intent.setComponent(intent);
startActivity(intent);
除此之外,Intent也提供了快捷的方法和建構函式:
-
setClass(Contextpkg, Class<?> cls)
-
setClassName(Contextpkg, Class<?> cls)
-
setClassName(Stringpkg, String cls)
-
Intent(Contextcontext, Class<?> cls)
下面是例子:
Intent intent1 = new Intent(getApplicationContext(), ActivityB.class); startActivity(intent1); Intent intent2 = new Intent(); intent2.setClass(getApplicationContext(), ActivityB.class); startActivity(intent2);
Action、Category屬性與Intent-Filter配置
Action、Category屬性值都為字串,其中Action表示Intent將要完成的一個抽象“動作”,Category用於為Action指定更加詳細的類別資訊或執行的環境,所以這兩個屬性一般會結合使用。
先通過一個例子來了解一下:
public class ActivityA extends Activity { public static final String ACTION_TEST = "com.gisirfive.ACTION_TEST"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Button button = new Button(this); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setAction(ACTION_TEST); startActivity(intent); } }); setContentView(button); } }
<application
……
<activity android:name=".ActivityB"> <intent-filter> <!--指定該Activity能響應Action為指定字串的Intent--> <action android:name="com.gisirfive.ACTION_TEST"/> </intent-filter> </activity> </application>
該例子是在ActivityA中點選按鈕,通過Action指定將要啟動的元件。從程式碼我們可以知道,startActivity()將會啟動ActivityB,但是ActivityA並不知道它會啟動ActivityB,它只知道它“想要啟動Action包含ACTION_TEST的元件”,這就是它的“意圖”。
使用隱式Intent的好處是避免了硬編碼的方式建立元件之間的互動。
上面程式中出現了Intent-Filter,我們知道它是放在元件(Android三個常用元件)裡面使用的,通常可以包含如下子元素:
-
0個或多個<action../>元素
-
0個或多個<category…/>元素
-
0個或1個<data …/>元素
這裡需要指出的是,雖然<intent-filter>可以包含多個Action元素,但是一個Intent物件最多隻能包含一個Action屬性,相當於“意圖”只能包含一個抽象動作。相反,Intent可以包含多個Category(Intent預設包含一個Intent.CAETGORY_DEFAULT常量,其值為android.intent.category.DEFAULT),這相當於“意圖”對這個抽象動作指定特定的執行環境。
指定Action、Category呼叫系統Activity
Intent不僅可以啟動本應用內的程式元件,也可以啟動Android系統的其他應用的程式元件,包括系統自帶的程式元件——只要許可權允許。
Android內部提供了大量標準Action、Category常量,其中用於啟動Activity的標準Action常量及對應的字串如下:
Action常量 |
對應字串 |
簡單說明 |
ACTION_MAIN |
android.intent.action.MAIN |
應用程式入口 |
ACTION_VIEW |
android.intent.action.VIEW |
顯示指定資料 |
ACTION_ATTACH_DATA |
android.intent.action.ATTACH_DATA |
指定某塊資料將被附加到其他地方 |
ACTION_EDIT |
android.intent.action.EDIT |
編輯指定資料 |
ACTION_PICK |
android.intent.action.PICK |
從列表中選擇某項並返回所選的資料 |
ACTION_CHOOSER |
android.intent.action.CHOOSER |
顯示一個Activity選擇器 |
ACTION_GET_CONTENT |
android.intent.action.GET_CONTENT |
讓使用者選擇資料,並返回所選資料 |
ACTION_DIAL |
android.intent.action.DIAL |
顯示撥號面板 |
ACTION_CALL |
android.intent.action.CALL |
直接向指定使用者打電話 |
ACTION_SEND |
android.intent.action.SEND |
向其他人傳送資料 |
ACTION_SENDTO |
android.intent.action.SENDTO |
向其他人傳送訊息 |
ACTION_ANSWER |
android.intent.action.ANSWER |
應答電話 |
ACTION_INSERT |
android.intent.action.INSERT |
插入資料 |
ACTION_DELETE |
android.intent.action.DELETE |
刪除資料 |
ACTION_RUN |
android.intent.action.RUN |
執行資料 |
ACTION_SYNC |
android.intent.action.SYNC |
執行資料同步 |
ACTION_PICK_ACTIVITY |
android.intent.action.PICK_ACTIVITY |
用於選擇Activity |
ACTION_SEARCH |
android.intent.action.SEARCH |
執行搜尋 |
ACTION_WEB_SEARCH |
android.intent.action.WEB_SEARCH |
執行Web搜尋 |
ACTION_FACTORY_TEST |
android.intent.action.FACTORY_TEST |
工廠測試的入口點 |
標準Category常量及對應的字串如下:
Category常量 |
對應字串 |
簡單說明 |
CATEGORY_DEFAULT |
android.intent.category.DEFAULT |
預設的Category |
CATEGORY_BROWSABLE |
android.intent.category.BROWSABLE |
指定該Activity能被瀏覽器安全呼叫 |
CATEGORY_TAB |
android.intent.category.TAB |
指定該Activity作為TabActivity的Tab頁 |
CATEGORY_LAUNCHER |
android.intent.category.LAUNCHER |
Activity顯示頂級程式列表中 |
CATEGORY_INFO |
android.intent.category.INFO |
用於提供包資訊 |
CATEGORY_HOME |
android.intent.category.HOME |
設定該Activity隨系統啟動而執行 |
CATEGORY_PREFERENCE |
android.intent.category.PREFERENCE |
該Activity是引數面板 |
CATEGORY_TEST |
android.intent.category.TEST |
該Activity是一個測試 |
CATEGORY_CAR_DOCK |
android.intent.category.CAR_DOCK |
指定手機被插入汽車底座(硬體)時執行該Activity |
CATEGORY_DESK_DOCK |
android.intent.category.DESK_DOCK |
指定手機被插入桌面底座(硬體)時執行該Activity |
CATEGORY_CAR_MODE |
android.intent.category.CAR_MODE |
設 |