1. 程式人生 > >你必須弄懂的Intent Filter匹配規則

你必須弄懂的Intent Filter匹配規則

Intent簡介

       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,只需要匹配任意一個即可啟動該元件。
例如:

<action android:name="com.wooyun.project.SHOW_CURRENT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/mpeg" android:scheme="http" . . . />
<data android:mimeType="image/*" />
<data android:scheme="http" android:type="video/*" />

(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-filter>
    <action android:name="android.intent.action.SEND"/>
    <action android:name="android.intent.action.SEND_TO"/>
</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部分組成

<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern >]

       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的語法:

<data android:scheme="String.“ 
          android:host="String"
          android:port="String"
          android:path="String"
          android:pathPattern="String"
          android:pathPrefix="String"
          android:mimeType="String"/>
    其中scheme、host等各個部分無需全部指定。

使用案例:
(1)如果我們想要匹配 http 以 “.pdf” 結尾的路徑,使得別的程式想要開啟網路 pdf 時,使用者能夠可以選擇我們的程式進行下載檢視。
我們可以將 scheme 設定為 “http”,pathPattern 設定為 “.*//.pdf”,整個 intent-filter 設定為:

<intent-filter>  
    <action android:name="android.intent.action.VIEW"></action>  
    <category android:name="android.intent.category.DEFAULT"></category>  
    <data android:scheme="http" android:pathPattern=".*//.pdf"></data>  
</intent-filter>  

如果你只想處理某個站點的 pdf,那麼在 data 標籤裡增加 android:host=”yoursite.com” 則只會匹配 http://yoursite.com/xxx/xxx.pdf,但這不會匹配 www.yoursite.com,如果你也想匹配這個站點的話,你就需要再新增一個 data 標籤,除了 android:host 改為 “www.yoursite.com” 其他都一樣。

(2)如果我們做的是一個IM應用,或是其他類似於微博之類的應用,如何讓別人通過 Intent 進行調用出現在選擇框裡呢?我們只用註冊 android.intent.action.SEND 與 mimeType 為 “text/plain” 或 “/” 就可以了,整個 intent-filter 設定為:

<intent-filter>  
    <action android:name="android.intent.action.SEND" />  
    <category android:name="android.intent.category.DEFAULT" />  
    <data mimeType="*/*" />  
</intent-filter> 

這裡設定 category 的原因是,建立的 Intent 的例項預設 category 就包含了 Intent.CATEGORY_DEFAULT ,google 這樣做的原因是為了讓這個 Intent 始終有一個 category。

這裡寫圖片描述

(3)如果我們做的是一個音樂播放軟體,當檔案瀏覽器開啟某音樂檔案的時候,使我們的應用能夠出現在選擇框裡?這類似於檔案關聯了,其實做起來跟上面一樣,也很簡單,我們只用註冊 android.intent.action.VIEW 與 mimeType 為 “audio/*” 就可以了,整個 intent-filter 設定為:

<intent-filter>  
     <action android:name="android.intent.action.VIEW" />  
     <category android:name="android.intent.category.DEFAULT" />  
     <data android: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。

特別說明:

<intent-filter>
    <action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

這二者共同出現,標明該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中的宣告如下:

<activity android:name="com.wooyun.org.MainActivity">
     <intent-filter>  
           <action android:name="com.google.test" />
           <category android:name="android.intent.category.DEFAULT" />
 </intent-filter> 
</activity>

(5)於intent-filter匹配優先順序

首先檢視Intent的過濾器(intent-filter),按照以下優先關係查詢:action->data->category

安卓開發高階技術交流QQ群:108721298 歡迎入群

微信公眾號:mobilesafehome

(本公眾號支援投票)

Android安全技術大本營

相關推薦

必須Intent Filter匹配規則

Intent簡介        Android中提供了Intent機制來協助應用間的互動與通訊,Intent負責對應用中一次操作的動作、動作涉及資料、附加資料進行描述,Android則根據此Intent的描述,負責找到對應的元件,將 Intent傳遞給呼叫的元

【行業動態】使用動態ip軟體前,這幾個概念必須

1、代理(Proxy)代理(英語:Proxy)也稱網路代理,是一種特殊的網路服務,允許一個網路終端(一般為客戶端)通過這個服務與另一個網路終端(一般為伺服器)進行非直接的連線。一些閘道器、路由器等網路安全裝置具備條件網路代理功能性。通常覺得代理服務有益於安全保障網路終端的隱私保護或安全性,避免進攻。代理伺服器

【行業動態】使用動態ip軟件前,這幾個概念必須

網絡代理 客戶端 數據包 必須 到來 路徑 由器 edi 計算 1、代理(Proxy)代理(英語:Proxy)也稱網絡代理,是一種特殊的網絡服務,允許一個網絡終端(一般為客戶端)通過這個服務與另一個網絡終端(一般為服務器)進行非直接的連接。一些網關、路由器等網絡安全設備具備

Activity的intent-filter匹配規則以及所有mimeType的所有寫法

當我們使用Intent intent = new Intent(Intent.ACTION_VIEW); startActivity(intent);這種方式啟動Activity的時候, 叫做隱式呼叫;隱式呼叫最重要的就是匹配規則,否則系統也不知道該啟動那個Activity;

德到課堂---必須的十大職場生存法則

活著 空間 可能 你會 是個 坐標 能說 孤單 得到 德到領袖與你分享:你必須要懂的十大職場生存法則在職場中,總需要有一些生存規則,那麽什麽樣的生存法則才適用呢,今天就來分享一下你必須要懂的十大職場中的生存規律。 01十大職場生存規律 第一:男女搭檔幹活不累。  在辦公室裏

Python工作好找嗎? 必須這6個祕訣工作就沒問題

隨著人工智慧時代的到來,Python的需求也變的越來越大了。從目前各大IT招聘網上顯示招聘需求是非常大,而且薪資基本都在10k起,高的可達40-50k 一、那找Python工作一般需要什麼要求呢?1、熟悉python編碼規範,良好的程式設計習慣;2、熟悉python基本資料型別的操作;3、熟悉python各

學好Java必須的知識點

Java21個技術點 程式設計師是一種神祕的人類物種,Java程式設計師更是! 今天給大家科普一下我在這麼多年的Java後臺開發後得出的經驗,Java的知識很多,有很多在工作中不經常用的,我這裡講的都是些經常用的吧 1、Java的執行(基礎必備) 起碼瞭解底層IDE又是如何執行

一文讓完全Stegosaurus

  一文讓你完全弄懂Stegosaurus 國內關於 Stegosaurus 的介紹少之又少,一般只是單純的工具使用的講解之類的,並且本人在學習過程中也是遇到了很多的問題,基於此種情況下寫下此文,也是為我逝去的青春時光留個念想吧~ Stegosaurus是什

Python工作好找嗎?必須這6個祕訣工作就沒問題

隨著人工智慧時代的到來,Python的需求也變的越來越大了。從目前各大IT招聘網上顯示招聘需求是非常大,而且薪資基本都在10k起,高的可達40-50k 一、那找Python工作一般需要什麼要求呢? 1、熟悉python編碼規範,良好的程式設計習慣; 2、熟悉p

通過分析漢語讓徹底充分條件必要條件,以及充要條件

前篇 我寫完自己簡要看了下,感覺語言有點複雜,大家慢慢品吧,內容是沒錯滴,如果有錯,歡迎探討 充分條件 看充分這個詞語 百度百科解釋得非常好,亦作”充份”,即足夠的份量,什麼意思?就是說已經完全可以滿足了,那麼充分條件就是完全可以滿足了的條件,那

php檔案上傳,了嗎?

這裡首先宣告一下這一章的內容比較多,比較難,你要抱著和自己死磕的態度。細微之處不放過,多敲多練是王道。 學習就像爬山,得一步一步來,首先給自己定一個小目標,然後再堅持不懈地往高出攀爬,最終到達最頂峰。 請仔細斟酌上面兩句忠告 一、我的準備情況說明。

.NETCore C# 中級篇2-4 一文帶完全正則表示式

.NETCoreCSharp 中級篇2-4 本節內容為正則表示式的使用 簡介 有的時候,你是否有過這種需求:判斷一個Ip地址、郵箱、密碼規則是否合法。如果讓你使用if一類的傳統方法進行處理,你肯定會被逼瘋的。而對於絕大多數的程式語言而言,都有一個字串處理利器————正則表示式。它可以輕鬆的讓字串和規則匹配

超乾貨!為了讓徹底MySQL事務日誌,我通宵肝出了這份圖解!

還記得剛上研究生的時候,導師常掛在嘴邊的一句話,“科研的基礎不過就是資料而已。”如今看來,無論是人文社科,還是自然科學,或許都可在一定程度上看作是資料的科學。 倘若剝開研究領域的外衣,將人的操作抽象出來,那麼科研的過程大概就是根據資料流動探索其中的未知資訊吧。當然科學研究的範疇涵蓋甚廣,也不是一兩句話能夠拎

深度揭祕垃圾回收底層,這次讓徹底

> Java 與 C++ 之間有一堵由記憶體動態分配和垃圾收集技術所圍成的高牆 ---《深入理解Java虛擬機器》 我們知道手動管理記憶體意味著自由、精細化地掌控,但是卻極度依賴於開發人員的水平和細心程度。 如果使用完了忘記釋放記憶體空間就會發生記憶體洩露,再如釋放錯了記憶體空間或者使用了懸垂指標則會發生

這次我讓徹底 RESTful

> 本文已收錄至 https://github.com/yessimida/yes ,這裡有我的所有文章分類彙總,歡迎 star! RESTful 想必大家都耳熟能詳。 但是為什麼要有 RESTful,RESTful 到底是什麼意思。 為什麼稱之為 RESTful 架構? 我不用 RESTful 不行

入坑/轉型人工智能必須的20個問題

編程程序 wrap 解決 back 1.5 應用層 答案 adding 轉型 一、前言昨晚做了一期關於《如何系統學習人工智能》的線上公開課,一個半小時,嗓子都冒煙了,看來這個行當還真不是一般人能做的來的。關於如何系統學習人工智能,線上回答了大家關於人工智能相關的很多問題,在

顯式和隱式Intent介紹及intent-filter的action,category,data匹配規則

Intent型別 Intent 分為兩種型別: 顯式 Intent:按名稱(完全限定類名)指定要啟動的元件。 通常,您會在自己的應用中使用顯式 Intent 來啟動元件,這是因為您知道要啟動的 Activity 或服務的類名。例如,啟動新 Activity 以響應使用者

徹徹底底Scroller

用兩個 author 官方文檔 adapt extends fadein ges script getch Scroller的使用 這是一個滑動幫助類。並不能夠使View真正的滑動,而是依據時間的流逝。獲取插值器中的數據。傳遞給我們。讓我們去配合s

網絡營銷?HTML,Javascript,語言太難?做網絡運營營銷,必須掌握的能力

廣告平臺 好的 更多 騰訊 互聯網營銷 點擊 事件 ali 系列 在如今的互聯網時代,有一個崗位是基本每家企業人事部都會常常掛在嘴邊的,網絡營銷人才,老板一直在招聘好的網絡營銷人才,因為他知道網絡營銷是每家企業都在爭奪的命脈。 網絡營銷人才就是簡單的互聯網+營銷。現在只懂互

如果想搞“分散式鎖”,必須要看這篇文章 ,看了很意外!

對於鎖大家肯定不會陌生,在 Java 中 synchronized 關鍵字和 ReentrantLock 可重入鎖在我們的程式碼中是經常見的,一般我們用其在多執行緒環境中控制對資源的併發訪問。 但是隨著分散式的快速發展,本地的加鎖往往不能滿足我們的需要,在我們的分散式環境中上面加鎖的方法