1 Intent簡介
? ??????Android中提供了Intent機制來協(xié)助應用間的交互與通訊,Intent負責對應用中一次操作的動作、動作涉及數(shù)據(jù)、附加數(shù)據(jù)進行描述,Android則根據(jù)此Intent的描述,負責找到對應的組件,將 Intent傳遞給調(diào)用的組件,并完成組件的調(diào)用。Intent不僅可用于應用程序之間,也可用于應用程序內(nèi)部的Activity/Service之間的交互。因此,Intent在這里起著一個媒體中介的作用,專門提供組件互相調(diào)用的相關信息,實現(xiàn)調(diào)用者與被調(diào)用者之間的解耦。在SDK中給出了Intent作用的表現(xiàn)形式為:
? ? 1、通過Context.startActivity()? ? orActivity.startActivityForResult() 啟動一個Activity;
? ? 2、通過 Context.startService() 啟動一個服務,或者通過Context.bindService() 和后臺服務交互;
? ? 3、通過廣播方法(比如 Context.sendBroadcast(),Context.sendOrderedBroadcast(),? Context.sendStickyBroadcast()),發(fā)給broadcast receivers。
? ??????Intent可分為隱式(implicitly)和顯式(explicitly)兩種:
1.1 顯式Intent
? ? ? ?即在構造Intent對象時就指定接收者,它一般用在知道目標組件名稱的前提下,一般是在相同的應用程序內(nèi)部實現(xiàn)的,如下:
Intent intent = new Intent(MainActivit.this, NewActivity.class);?
startActivity(intent );
????????上面那個intent中,直接指明了接收者:NewActivity
1.2 隱式Intent
????????即Intent的發(fā)送者在構造Intent對象時,并不知道也不關心接收者是誰,有利于降低發(fā)送者和接收者之間的耦合,它一般用在沒有明確指出目標組件名稱的前提下,一般是用于在不同應用程序之間,如下:
Intent intent = new Intent();
intent.setAction("com.wooyun.test");
startActivity(intent);
????????上面那個intent,沒有指明接收者,只是給了一個action作為接收者的過濾條件。
??? ????對于顯式Intent,Android不需要去做解析,因為目標組件已經(jīng)很明確,Android需要解析的是那些隱式Intent,通過解析,將Intent映射給可以處理此Intent的Activity、IntentReceiver或Service。
1.3 Intent Filter匹配規(guī)則
????????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.3.1 (1)action的匹配規(guī)則
? ? ? ?action是一個字符串,如果Intent指明定了action,則目標組件的IntentFilter的action列表中就必須包含有這個action,否則不能匹配。一個Intent Filter中可聲明多個action,Intent中的action與其中的任一個action在字符串形式上完全相同(注意,區(qū)分大小寫,大小寫不同但字符串內(nèi)容相同也會造成匹配失?。?,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系統(tǒng)預定義了許多action,這些action代表了一些常見的操作。常見action如下(Intent類中的常量):
????Intent.ACTION_VIEW
????Intent.ACTION_DIAL
????Intent.ACTION_SENDTO
????Intent.ACTION_SEND
????Intent.ACTION_WEB_SEARCH
1.3.2 (2)data的匹配規(guī)則
????????如果Intent沒有提供type,系統(tǒng)將從data中得到數(shù)據(jù)類型。和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>]
????????例如:?
content://com.wooyun.org:200/folder/etc?
http://www.wooyun.org:80/search/info
? ? ? ?Intent的uri可通過setData方法設置,mimetype可通過setType方法設置。?需要注意的是:若Intent Filter的data聲明部分未指定uri,則缺省uri為content或file,Intent中的uri的scheme部分需為content或file才能匹配;若要為Intent指定完整的data,必須用setDataAndType方法,究其原因在,setData和setType方法的源碼中我們發(fā)現(xiàn):
? ??path、pathPrefix、pathPattern?之間的區(qū)別
? ??????這里主要說的區(qū)別是?path、pathPrefix、pathPattern?之間的區(qū)別:
????· path?用來匹配完整的路徑,如:http://example.com/blog/abc.html,這里將 path 設置為 /blog/abc.html 才能夠進行匹配;
????· pathPrefix?用來匹配路徑的開頭部分,拿上來的 Uri 來說,這里將 pathPrefix 設置為 /blog 就能進行匹配了;
????· pathPattern?用表達式來匹配整個路徑,這里需要說下匹配符號與轉(zhuǎn)義。
????匹配符號:
????1. “*” 用來匹配0次或更多,如:“a*” 可以匹配“a”、“aa”、“aaa”...
????2. “.” 用來匹配任意字符,如:“.” 可以匹配“a”、“b”,“c”...
????3. 因此 “.*” 就是用來匹配任意字符0次或更多,如:“.*html” 可以匹配“abchtml” 、 “chtml”、 “html”、“sdf.html”...
????????轉(zhuǎn)義:因為當讀取 Xml 的時候,“/” 是被當作轉(zhuǎn)義字符的(當它被用作 pathPattern 轉(zhuǎn)義之前),因此這里需要兩次轉(zhuǎn)義,讀取 Xml 是一次,在 pathPattern 中使用又是一次。如:“*” 這個字符就應該寫成 “//*”,“/” 這個字符就應該寫成 “////”。
2 IntentFilter跳轉(zhuǎn)方案
2.1 方案設計
2.1.1 跳轉(zhuǎn)App方案
????????流程方案是在Android工程的AndroidManifest.xml中,將LauncherActivity作為拉起App后的頁面,在微信文章頁面,分兩種情況處理:
????1、對于能支持直接跳轉(zhuǎn)的,例如華為、小米等大部分手機,引導用戶通過右上角點擊“在瀏覽器中打開”按鈕,然后頁面會彈出目標App的選項框;


????2、對于不能支持直接跳轉(zhuǎn)的,例如三星S7,則跳轉(zhuǎn)到應用寶頁面,利用微信的跳轉(zhuǎn)來打開;
2.1.2 App中子頁面跳轉(zhuǎn)方案設計
????????依托原有的linkType與localPath外網(wǎng)跳轉(zhuǎn)方案,在微信位置的跳轉(zhuǎn)鏈接中加上linkType與localPath兩個參數(shù),用來拉起App的具體二級頁面。而拉起頁面后,導航條數(shù)據(jù)則通過localPath直接從js端獲取就行。
2.2 核心代碼
核心代碼示例如下:

我們App中Url Scheme設計如下:

2.3 落地方案
2.3.1 域名規(guī)劃
????????Android中是通過域名+一級路徑來支持url跳轉(zhuǎn)App,目前預研時支持官網(wǎng)指定路徑與微信的指定目錄的所有路徑的跳轉(zhuǎn)。
2.3.2 跳轉(zhuǎn)后頁面呈現(xiàn)方案設計
????????在HJDev的架構中,App中打開的頁面分為了外網(wǎng)、微信文章、活動、本地web頁面、原生頁面這幾類,通過linkType來標記。故在微信App中調(diào)起App后,可通過url參數(shù)將linkType、目標頁面url傳遞過來。而HJDev App依據(jù)此內(nèi)容直接創(chuàng)建對應頁面的實例入棧顯示。
????????其中要注意的細節(jié)點是,頁面原生導航欄的描述數(shù)據(jù)可以使用url從h5端動態(tài)獲取。
String *jsonStr = "hj.NativeViewUtil.NavDataFactory.getNavDataByPathForJson(" + localRePath + '')";
????????故在微信跳轉(zhuǎn)地址中,需要傳遞如下參數(shù):
??????????? linkType, localpath,如果目標頁面需要傳遞參數(shù),則localpath中必須帶上。
????LinkType取值規(guī)則如下:
??????????? 0:普通web頁面;
??????????? 1:活動頁面;
??????????? 2:微信文章頁面;
??????????? 3:本地web頁面;
??????????? 4:原生頁面;
2.3.3 原生端跳轉(zhuǎn)規(guī)則設計:
????1、只對hjdev.com域名url進行攔截處理;
????2、如果url中不包含localpath參數(shù),則分兩種情況:
????????a) 如果是wx相關域名,則直接取url做路由入棧跳轉(zhuǎn);
????????b) 其他的(包括不含參數(shù)情況),則直接跳轉(zhuǎn)首頁;
????3、如果包含localpath參數(shù),則分兩種情況:
????????a) 如果localpath參數(shù)為-1,則取當前url做路由入棧跳轉(zhuǎn);
????????b) 如果localpath參數(shù)為-2,則直接拉起App;
????????c) 如果參數(shù)值是一個url,則進行urlDecode處理后,做路由入棧跳轉(zhuǎn);
????????d) 否則直接拉起App;
????4、做路由入棧跳轉(zhuǎn)時,應將linktype參數(shù)也攜帶進去,同時根據(jù)url從h5獲取頭部數(shù)據(jù)結構也攜帶進去;
3 參考鏈接
iOS/Android瀏覽器(h5)及微信中喚起本地APP
http://www.cnblogs.com/shadajin/p/5724117.html
(Good)android/iPhone:如何從browser直接打開應用程序或者打開應用商店(如果沒有應用程序)
http://blog.csdn.net/hundsong/article/details/6623500
Android平臺好友點擊微信分享的內(nèi)容后跳轉(zhuǎn)來源App的實現(xiàn)方案研究
http://www.2cto.com/kf/201409/330877.html
Android開發(fā)--Intent-filter屬性詳解
http://blog.csdn.net/wuwenxiang91322/article/details/7671593#
?你必須弄懂的IntentFilter匹配規(guī)則
http://blog.csdn.net/mynameishuangshuai/article/details/51673273
Intent和IntentFilter詳解
http://blog.csdn.net/cnnumen/article/details/8464786
(Good)iOS/Android瀏覽器(h5)及微信中喚起本地APP
http://www.cnblogs.com/shadajin/p/5724117.html
Android開發(fā)之Intent.Action
http://www.cnblogs.com/hanyonglu/archive/2012/03/26/2417278.html
(Good)在手機的瀏覽器上通過連接打開App
http://www.cnblogs.com/sexintercourse/p/5898242.html
更新:通過瀏覽器直接打開Android應用程序
https://my.oschina.net/liucundong/blog/354029
(Good)Android實現(xiàn)通過瀏覽器點擊鏈接打開本地應用(APP)并拿到瀏覽器傳遞的數(shù)據(jù)
http://blog.csdn.net/jiangwei0910410003/article/details/23940445