Android 之Intent,Filter和IntentFilter
Intent(意圖)/Filter(過濾器)
Android意圖(Intent)是一個要執行的操作的抽象描述。它可以通過 startActivity 來啓動一個活動,broadcastIntent 來發送廣播到任何對它感興趣的廣播接受器組件,startService(Intent) 或者bindService(Intent, ServiceConnection, int) 來與後臺服務通訊。
意圖本身(一個 Intent 對象)是一個被動的數據結構,保存着要執行操作的抽象描述。
接收意圖(Intent)等方法
- Context.startActivity():意圖傳遞給該方法,用於啓動一個新的活動或者讓已存在的活動做一些新的事情。
- Context.startService():意圖傳遞給該方法,將初始化一個服務,或者新的信息到一個持續存在的服務。
- Context.sendBroadcast():意圖傳遞給該方法,信息將傳遞到所有對此感興趣的廣播接收器。
意圖對象
意圖對象是一包的信息,用於組件接收到的意圖就像 Android 系統接受到的信息。
意圖對象包括如下的組件,具體取決於要通信或者執行什麼。
動作(Action)
這是意圖對象中必須的部分,被表現爲一個字符串。在廣播的意圖中,動作一旦發生,將會被報告。動作將很大程度上決定意圖的其他部分如何被組織。Intent 類定義了一系列動作常量對應不同的意圖。這裏是一份Android意圖標準動作 列表。
意圖對象中的動作可以通過 setAction() 方法來設置,通過 getAction() 方法來讀取。
數據(Data)
添加數據規格到意圖過濾器。這個規格可以只是一個數據類型(如元類型屬性),一條 URI ,或者同時包括數據類型和 URI 。 URI 則由不同部分的屬性來指定。
這些指定 URL 格式的屬性是可選的,但是也相互獨立 -
- 如果意圖過濾器沒有指定模式,所有其他的 URI 屬性將被忽略。
- 如果沒有爲過濾器指定主機,端口屬性和所有路徑屬性將被忽略。
setData() 方法只能以 URI 來指定數據,setType() 只能以元類型指定數據,setDataAndType() 可以同時指定 URI 和元類型。URI 通過 getData() 讀取,類型通過 getType() 讀取。
動作/數據組的一些實例
- ACTION_VIEW content://contacts/people/1:顯示ID爲1的用戶的信息。
- ACTION_DIAL content://contacts/people/1:顯示電話撥號器,並填充用戶1的數據。
- ACTION_VIEW tel:123:顯示電話撥號器,並填充給定的號碼。
- ACTION_DIAL tel:123:顯示電話撥號器,並填充給定的號碼。
- ACTION_EDIT content://contacts/people/1:編輯ID爲1的用戶信息。
- ACTION_VIEW content://contacts/people/:顯示用戶列表,以便查看。
- ACTION_SET_WALLPAPER:顯示選擇壁紙設置。
- ACTION_SYNC:同步數據,默認的值爲:android.intent.action.SYNC
- ACTION_SYSTEM_TUTORIAL:開啓平臺定義的教程(默認教程或者啓動教程)
- ACTION_TIMEZONE_CHANGED:當時區被改變時通知
- ACTION_UNINSTALL_PACKAGE:運行默認的卸載器
意圖的類型
Android 支持兩種類型的意圖,顯示意圖,隱式意圖。
顯式意圖
顯式意圖用於連接應用程序的內部世界,假設你需要連接一個活動到另外一個活動,我們可以通過顯示意圖,下圖顯示通過點擊按鈕連接第一個活動到第二個活動。
這些意圖通過名稱指定目標組件,一般用於應用程序內部信息 - 比如一個活動啓動一個下屬活動或者啓動一個兄弟活動。舉個例子:
// 通過指定類名的顯式意圖
Intent i = new Intent(FirstActivity.this, SecondAcitivity.class);
// 啓動目標活動
startActivity(i);
隱式意圖
這些意圖沒有爲目標命名,組件名稱的域爲空。隱式意圖經常用於激活其他應用程序的組件。舉個例子:
Intent read1=new Intent();
read1.setAction(android.content.Intent.ACTION_VIEW);
read1.setData(ContactsContract.Contacts.CONTENT_URI);
startActivity(read1);
目標組件接收到意圖,可以使用getExtras()方法來獲取由源組件發送的附加數據。例如:
// 在代碼中的合適位置獲取包對象
Bundle extras = getIntent().getExtras();
// 通過鍵解壓數據
String value1 = extras.getString("Key1");
String value2 = extras.getString("Key2");
IntentFilter
IntentFilter就是“意圖過濾器”,主要用來過濾隱式意圖。當用戶進行一項操作的時候,Android系統會根據配置的 “意圖過濾器” 來尋找可以響應該操作的組件,服務。
例子
Android系統就會通過設定好的意圖過濾器,進行匹配測試,找到能夠打開PDF文件的APP程序代碼如下:
<activity android:name="com.example.testmain.ShowActivity" >
<intent-filter>
<action android:name="test.update.mydata" />
<category android:name="my.test.show" />
<data android:pathPattern=".*\\.jpg" android:scheme="http" />
</intent-filter>
</activity>
IntentFilter 如何過濾隱式意圖
Android系統會根據我們配置的Intent Filter(意圖過濾器),來進行匹配測試。匹配的時候,只會考慮三個方面:動作、數據(URI以及數據類型)和類別。也就是說Android系統會進行“動作測試”,“數據測試”,“類別測試”,來尋找可以響應隱式意圖的組件或服務。
另外,當對其他App程序開放組件和服務的時候也需要配置Intent Filter(意圖過濾器),一個Activity可以配置多個< intent-filter >。
動作測試:
對應中的標籤;
(1) 如果標籤中有多個,那麼Intent請求的Action,只要匹配其中的一條就可以通過了這條的動作測試。
(2) 如果中沒有包含任何,那麼無論什麼Intent請求都無法和這條匹配。
(2) 如果Intent請求中沒有設定Action(動作),那麼這個Intent請求就將順利地通過的動作測試(前提是中必須包含有,否則與第二條衝突)。
類別測試:
對應< intent-filter>中的< category />標籤;
Intent中的類別必須全部匹配< intent-filter>中的< category />,但是< intent-filter>中多餘的< category />將不會導致匹配失敗。
例如:Intent中有3個類別,而意圖過濾器中定義了5個,如果Intent中的3個類別都與過濾器中的匹配,那麼過濾器中的另外2個,將不會導致類別測試失敗。
數據測試:
對應< intent-filter>中的< data>標籤;
< data>元素指定了可以接受的Intent傳過來的數據URI和數據類型,當一個意圖對象中的URI被用來和一個過濾器中的URI比較時,比較的是URI的各個組成部分。
例如:
如果過濾器僅指定了一個scheme,所有該scheme的URIs都能夠和這個過濾器相匹配;
如果過濾器指定了一個scheme、主機名但沒有路經部分,所有具有相同scheme和主機名的URIs都可以和這個過濾器相匹配,而不管它們的路經;
如果過濾器指定了一個scheme、主機名和路經,只有具有相同scheme、主機名和路經的URIs纔可以和這個過濾器相匹配。
當然,一個過濾器中的路徑規格可以包含通配符,這樣只需要部分匹配即可。