Intent對於Android應用的作用
Intent,翻譯過來是“意圖”,它是對Android應用程序“意圖”的封裝。例如ActivityA想啓動ActivityB,那麼“想啓動ActivityB”就是ActivityA的意圖;ActivityA想啓動ServiceA,“想啓動ServiceA”就是ActivityA的意圖。
至於Android爲什麼不直接提供一個類似startActivity(Class activityClass)的方法來移動一個Activity,是因爲這樣做會背離Android的設計理念,造成一種硬編碼耦合,不利於高層次的解耦。而Intent提供的編程模型,可以讓應用程序只啓動具有某種特徵額組件,不會造成組件(Activity、Service、ContentProvider)之間的耦合。
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 |
設置該Activity可在車載環境下使用 |
下面是一個返回桌面的例子:
private void fackBackHome(){ Intent intent = new Intent(); intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); startActivity(intent); }