你必須弄懂的Intent Filter匹配規則
Android中提供了Intent機制來協助應用間的互動與通訊,Intent負責對應用中一次操作的動作、動作涉及資料、附加資料進行描述,Android則根據此Intent的描述,負責找到對應的元件,將 Intent傳遞給呼叫的元件,並完成元件的呼叫。Intent不僅可用於應用程式之間,也可用於應用程式內部的Activity/Service之間的互動。因此,Intent在這裡起著一個媒體中介的作用,專門提供元件互相呼叫的相關資訊,實現呼叫者與被呼叫者之間的解耦。在SDK中給出了Intent作用的表現形式為:
- 透過Context.startActivity() orActivity.startActivityForResult()
啟動一個Activity; - 透過 Context.startService() 啟動一個服務,或者透過Context.bindService() 和後臺服務互動;
-
透過廣播方法(比如 Context.sendBroadcast(),Context.sendOrderedBroadcast(),
Context.sendStickyBroadcast()) 發給broadcast receivers。Intent可分為隱式(implicitly)和顯式(explicitly)兩種:
(1)顯式 Intent
即在構造Intent物件時就指定接收者,它一般用在知道目標元件名稱的前提下,一般是在相同的應用程式內部實現的,如下:
Intent intent = new Intent(MainActivit.this, NewActivity.class);
startActivity(intent );
上面那個intent中,直接指明瞭接收者:NewActivity
(2)隱式 Intent
即Intent的傳送者在構造Intent物件時,並不知道也不關心接收者是誰,有利於降低傳送者和接收者之間的耦合,它一般用在沒有明確指出目標元件名稱的前提下,一般是用於在不同應用程式之間,如下:
Intent intent = new Intent();
intent.setAction("com.wooyun.test");
startActivity(intent);
上面那個intent,沒有指明接收者,只是給了一個action作為接收者的過濾條件。
對於顯式Intent,Android不需要去做解析,因為目標元件已經很明確,Android需要解析的是那些隱式Intent,透過解析,將Intent對映給可以處理此Intent的Activity、IntentReceiver或Service。
Intent Filter匹配規則Intent解析機制主要是透過查詢已註冊在AndroidManifest.xml中的所有IntentFilter及其中定義的Intent,最終找到匹配的Intent。在這個解析過程中,Android是透過Intent的action、type、category這三個屬性來進行匹配判斷的。一個過濾列表中的action、type、category可以有多個,所有的action、type、category分別構成不同類別,同一類別資訊共同約束當前類別的匹配過程。只有一個Intent同時匹配action、type、category這三個類別才算完全匹配,只有完全匹配才能啟動Activity。另外一個元件若宣告瞭多個Intent Filter,只需要匹配任意一個即可啟動該元件。
例如:
(1)action的匹配規則
action是一個字串,如果Intent指明定了action,則目標元件的IntentFilter的action列表中就必須包含有這個action,否則不能匹配。一個Intent Filter中可宣告多個action,Intent中的action與其中的任一個action在字串形式上完全相同(注意,區分大小寫,大小寫不同但字串內容相同也會造成匹配失敗),action方面就匹配成功。可透過setAction方法為Intent設定action,也可在構造Intent時傳入action。需要注意的是,隱式Intent必須指定action。比如我們在Manifest檔案中為MyActivity定義瞭如下Intent Filter:
那麼只要Intent的action為“SEND”或“SEND_TO”,那麼這個Intent在action方面就能和上面那個Activity匹配成功。比如我們的Intent定義如下:
Intent intent = new Intent("android.intent.action.SEND") ;
startActivity(intent);
那麼我們的Intent在action方面就與MyActivity匹配了。
Android系統預定義了許多action,這些action代表了一些常見的操作。常見action如下(Intent類中的常量):
Intent.ACTION_VIEW
Intent.ACTION_DIAL
Intent.ACTION_SENDTO
Intent.ACTION_SEND
Intent.ACTION_WEB_SEARCH
(2)data的匹配規則
如果Intent沒有提供type,系統將從data中得到資料型別。和action一樣,同action類似,只要Intent的data只要與Intent Filter中的任一個data宣告完全相同,data方面就完全匹配成功。
data由兩部分組成:mimeType和URI
MineType指的是媒體型別:例如imgage/jpeg,auto/mpeg4和viedo/*等,可以表示圖片、文字、影片等不同的媒體格式
uri則由scheme、host、port、path | pathPattern | pathPrefix這4部分組成
://:/[||]
例如:
content://com.wooyun.org:200/folder/etc
Intent的uri可透過setData方法設定,mimetype可透過setType方法設定。
需要注意的是:若Intent Filter的data宣告部分未指定uri,則預設uri為content或file,Intent中的uri的scheme部分需為content或file才能匹配;若要為Intent指定完整的data,必須用setDataAndType方法,究其原因在,setData和setType方法的原始碼中我們發現:
public Intent setData(Uri data) {
mData = data;
mType = null;
return this;
}
public Intent setType(String type) {
mData = null;
mType = type;
return this;
}
這兩個方法會彼此互相清除對方的值(這個比較逗),即setData會把mimeType置為null,setType會把uri置為null。
下面我們來舉例說明一下data的匹配。首先我們先來看一下Intent Filter中指定data的語法:
其中scheme、host等各個部分無需全部指定。
使用案例:
(1)如果我們想要匹配 http 以 “.pdf” 結尾的路徑,使得別的程式想要開啟網路 pdf 時,使用者能夠可以選擇我們的程式進行下載檢視。
我們可以將 scheme 設定為 “http”,pathPattern 設定為 “.*//.pdf”,整個 intent-filter 設定為:
,但這不會匹配 ,如果你也想匹配這個站點的話,你就需要再新增一個 data 標籤,除了 android:host 改為 “” 其他都一樣。 (2)如果我們做的是一個IM應用,或是其他類似於微博之類的應用,如何讓別人透過 Intent 進行呼叫出現在選擇框裡呢?我們只用註冊 android.intent.action.SEND 與 mimeType 為 “text/plain” 或 “/” 就可以了,整個 intent-filter 設定為:
這裡設定 category 的原因是,建立的 Intent 的例項預設 category 就包含了 Intent.CATEGORY_DEFAULT ,google 這樣做的原因是為了讓這個 Intent 始終有一個 category。
(3)如果我們做的是一個音樂播放軟體,當檔案瀏覽器開啟某音樂檔案的時候,使我們的應用能夠出現在選擇框裡?這類似於檔案關聯了,其實做起來跟上面一樣,也很簡單,我們只用註冊 android.intent.action.VIEW 與 mimeType 為 “audio/*” 就可以了,整個 intent-filter 設定為:
(3)category的匹配規則
category也是一個字串,但是它與action的過濾規則不同,它要求Intent中個如果含有category,那麼所有的category都必須和過濾規則中的其中一個category相同。也就是說,Intent中如果出現了category,不管有幾個category,對於每個category來說,它必須是過濾規則中的定義了的category。當然,Intent中也可以沒有category(若Intent中未指定category,系統會自動為它帶上“android.intent.category.DEFAULT”),如果沒有,仍然可以匹配成功。category和action的區別在於,action要求Intent中必須有一個action且必須和過濾規則中的某幾個action相同,而category要求Intent可以沒有category,但是一旦發現存在category,不論你有多少,每個都要能夠和過濾規則中的任何一個category相同。我們可以透過addCategory方法為Intent新增category。
特別說明:
這二者共同出現,標明該Activity是一個入口Activity,並且會出現在系統應用列表中,二者缺一不可。
Intent Filter常見問題彙總 (1)path、pathPrefix、pathPattern 之間的區別
path 用來匹配完整的路徑,如:http://example.com/blog/abc.html,這裡將 path 設定為 /blog/abc.html 才能夠進行匹配;
pathPrefix 用來匹配路徑的開頭部分,拿上來的 Uri 來說,這裡將 pathPrefix 設定為 /blog 就能進行匹配了;
pathPattern 用表示式來匹配整個路徑,這裡需要說下匹配符號與轉義。
匹配符號:
“” 用來匹配0次或更多,如:“a” 可以匹配“a”、“aa”、“aaa”…
“.” 用來匹配任意字元,如:“.” 可以匹配“a”、“b”,“c”…
因此 “.” 就是用來匹配任意字元0次或更多,如:“.html” 可以匹配 “abchtml”、“chtml”,“html”,“sdf.html”…
轉義:因為當讀取 Xml 的時候,“/” 是被當作跳脫字元的(當它被用作 pathPattern 轉義之前),因此這裡需要兩次轉義,讀取 Xml 是一次,在 pathPattern 中使用又是一次。如:“” 這個字元就應該寫成 “//”,“/” 這個字元就應該寫成 “////”。
(2)查詢是否有Activity可以匹配我們指定Intent的元件
採用PackageManager的resolveActivity或者Intent的resolveActivity方法會獲得最適合Intent的一個Activity
呼叫PackageManager的queryIntentActivities會返回所有成功匹配Intent的Activity
(3)android.intent.action.MAIN 與android.intent.category.LAUNCHER的區別
區別一:
android.intent.action.MAIN決定一個應用程式最先啟動那個元件
android.intent.category.LAUNCHER決定應用程式是否顯示在程式列表裡(說白了就是是否在桌面上顯示一個圖示)
這兩個屬性組合情況:
第一種情況:有MAIN,無LAUNCHER,程式列表中無圖示
原因:android.intent.category.LAUNCHER決定應用程式是否顯示在程式列表裡
第二種情況:無MAIN,有LAUNCHER,程式列表中無圖示
原因:android.intent.action.MAIN決定應用程式最先啟動的Activity,如果沒有Main,則不知啟動哪個Activity,故也不會有圖示出現 ,所以這兩個屬性一般成對出現。
如果一個應用中有兩個元件intent-filter都新增了android.intent.action.MAIN和
android.intent.category.LAUNCHER這兩個屬性, 則這個應用將會顯示兩個圖示, 寫在前面的元件先執行。
區別二:
android.intent.category.LAUNCHER:android.intent.category.LAUNCHER決定應用程式是否顯示在程式列表裡,就是android開機後的主程式列表。
android.intent.category.HOME:按住“HOME”鍵,該程式顯示在HOME列表裡。
(4)關於隱式intent
每一個透過 startActivity() 方法發出的隱式 Intent 都至少有一個 category,就是 “android.intent.category.DEFAULT”,所以只要是想接收一個隱式 Intent 的 Activity 都應該包括 “android.intent.category.DEFAULT” category,不然將導致 Intent 匹配失敗.
比如說一個activity元件要想被其他元件透過隱式intent呼叫, 則其在manifest.xml中的宣告如下:
http://blog.csdn.net/cnnumen/article/details/8464786
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4798/viewspace-2799789/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android中的Intent Filter匹配規則介紹AndroidIntentFilter
- 正則匹配規則2
- 正則匹配規則記錄
- nginx location匹配規則Nginx
- 你必須知道的 SmartSql !SQL
- Nginx匹配規則練習Nginx
- modsecurity:規則例子:匹配url
- nginx的location 規則匹配練習Nginx
- 你必須做到的 3 件事
- Git中~你必須掌握的!Git
- 【筆記】【Android】Manifest中的intent-filter使用筆記AndroidIntentFilter
- 【行業動態】使用動態ip軟體前,這幾個概念你必須弄懂!行業
- nginx location匹配及rewrite規則Nginx
- ?你必須知道的Java泛型Java泛型
- 你必須讓他停下
- 匹配必須帶有埠號的網址或者IP地址
- 一文弄懂Nginx的location匹配Nginx
- php正則匹配所有違規字元PHP字元
- 徹底弄懂 Nginx location 匹配Nginx
- CSS你可以不寫,但這些規範必須要知道!CSS
- 你必須知道的HTTP基本概念HTTP
- 你必須瞭解Spring的生態Spring
- 你必須懂的前端效能優化前端優化
- 你必須要知道的babel二三事Babel
- servlet的url-pattern匹配規則詳細描述Servlet
- go Casbin配置檔案,以及匹配規則Go
- 理解 React Hooks 心智模型:必須按順序、不能在條件語句中呼叫的規則ReactHook模型
- 您必須知道的 Git 分支開發規範Git
- 3款你必須知道的爬蟲工具爬蟲
- 你必須搞清楚的String,StringBuilder,StringBufferUI
- .Net Core 你必須知道的source-generators
- 函式你必須知道的三種角色?函式
- C#.NET 中你必須知道的反射C#反射
- 敲黑板:InnoDB的Double Write,你必須知道
- 你必須知道的Java基礎知識Java
- is 和 as 讀你必須知道的.net 筆記筆記
- 你必須要知道的HTTP協議原理HTTP協議
- 寶鯤財經:投資必須知道的15法則