iOS應用間通信:URL Schemes

iOS應用間通信:URL Schemes

拋開越獄不談,URL Schemes幾乎是iOS應用間通信(Inter-app Communication)的唯一選擇(另一種是Air Drop,但主要用于共享大文件),其重要性毋庸置疑。

更新:Apple在iOS9推出了Universal Links,同樣基于URL,力求統一原生應用和web服務的用戶體驗,可視為URL Schemes的全面升級。當然,其實現也更為復雜。

A. 什么是URL Schemes

URL用于定位資源,譬如網絡資源。以下面的URL為例:

http://www.example.com/index.php?key1=value1&key2=value2

根據RFC1808標準,其包含如下組成部分:

內容 角色 作用
http scheme 服務類型。注意,http是一種互聯網協議,但理論上任意合法字符串都可以充當scheme
www.example.com host 主機域名
index.php path 資源路徑
key1=value1&key2=value2 query 參數

iOS中,你可以為自己的應用定義URL schemes,供外界調用。URL格式必須符合標準(即能夠通過NSURL解析)。

總體來說,URL schemes可劃分為兩類:系統定義&自定義。

B. 系統定義的URL Schemes

有些系統應用天生支持URL schemes,例如電話,郵件,短信,Safari,地圖等。

/ scheme 范例 效果 備注
電話 tel tel:16812345678 撥打號碼16812345678 電話號碼必傳
郵件 mailto mailto:frank@163.com frank@163.com寫郵件 郵件地址必傳
短信 sms sms:16812345678 編寫發送給號碼16812345678的短信 電話號碼不是必傳,如不傳,則僅打開短信應用
Safari http(s) https://www.baidu.com 在Safari中打開網頁 絕大部分http地址都默認使用Safari打開
地圖 http(s) http://maps.apple.com/?q=四川菜 搜索附近的四川菜。注意,url含有中文時要編碼 地圖的scheme并不是map,而是一個host為maps.apple.com的http地址

更多關于系統定義的URL schemes的信息,詳見官方文檔Apple URL Scheme Reference

C. 調用URL Scheme

調用URL scheme其實很簡單,分為兩步:

  1. 創建URL;
  2. 要求UIApplication打開它;

注意事項:

  • 調用特定app,必須事先知道其scheme;
  • 除scheme外,有些app還要求傳遞額外信息;信息錯誤,可能無法達到預期效果;
  • 自定義schemes與系統schemes發生沖突,默認以后者為準;
  • 多個app注冊同一個scheme,調用結果未知;

打開URL的方法如下:

- (void)openURL:(NSURL *)URL completionHandler:(void (^)(BOOL success))completionHandler;
  • 此方法自iOS10引入,低版本請使用openURL:
  • 回調completionHandler攜帶一個布爾參數success,表示是否成功打開URL。注意,這里的成功意味著有app響應URL scheme,從而被調起;至于URL是否被成功處理,不得而知;
  • 也就是說,只要scheme正確,一定會有app被調起,回調一定顯示成功;

我們可以嘗試通過Safari調用某個scheme,具體做法為:在地址欄里輸入targetScheme://,將targetScheme替換為具體scheme即可。注意,://不可省略;如果包含中文,必須編碼。

D. 自定義URL Schemes

自定義URL schemes也可以分為兩步:

  1. 注冊schemes;
  2. 處理調用請求。

D.1 注冊schemes

iOS以URL type為單位管理URL schemes。一個type下可以有多個scheme,但一個scheme只對應一個type。注冊URL schemes,實際上是注冊URL type。

Info.plist中添加鍵值對CFBundleURLTypes,其對應一個數組,每個元素都是一個字典,代表一個type。例如:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLIconFile</key>
        <string>iconGinx</string>
        <key>CFBundleURLName</key>
        <string>cn.com.rap.ginx</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>wb2522720237</string>
            <string>wxd3a1541d4423bf8f</string>
            <string>ddyc</string>
            <string>tencent1101352712</string>
            <string>navigationMapBack</string>
        </array>
    </dict>
    <!--其他URL type...-->
<array>

一個URL type字典包含如下鍵值對:

必填 備注
CFBundleURLSchemes 字符串數組,一個字符串代表一個scheme 一個type下可以有多個scheme
CFBundleURLName type的識別符,必須唯一。推介使用反向DNS風格的命名方式,如com.myhost.myscheme。 具體作用不詳
CFBundleURLIconFile type的圖標名稱 圖標用途不詳
CFBundleTypeRole app在type中所扮演的角色 具體作用不詳,使用默認值即可

更多關于CFBundleURLTypes的信息,詳見Information Property List Key Reference中章節CFBundleURLTypes的敘述。

此外,還可以針對scheme定義啟動圖片。眾所周知,app啟動時會顯示圖片。如果app因為響應某個scheme而啟動,可以根據scheme定義圖片。圖片命名格式如下:

<basename> -<url_scheme> <other_modifiers> .png

更多關于URL scheme啟動圖片的信息,詳見App Programming Guide for iOS中章節Displaying a Custom Launch Image When a URL is Opened的敘述。

D.2 處理調用請求

D.2.1 處理邏輯

收到調用請求后,相應的UIApplication代理方法會被調用,所以這里也是處理邏輯的所在:

// UIApplicationDelegate
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options

注意事項:

D.2.2 生命周期

被調用時,app可能處于下列狀態之一:

  1. app未運行;
  2. app運行中,但在后臺或被掛起;

D.2.2.1 app未運行時被調用

app先啟動,再處理請求,但受到下面方法影響:

// UIApplicationDelegate
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
  • 如果任意方法返回NO,則不處理請求(即方法application:openURL:options:不調用);
  • 如果只實現其中一個,則以實現的那個為準;
  • 即使不處理請求,app仍會啟動,進入前臺;調用者收到成功回調(方法openURL:completionHandler:回調參數顯示成功);

D.2.2.1 app運行中被調用

app必定會處理請求,進入前臺(即方法application:openURL:options:一定會被調用);

E. LSApplicationQueriesSchemes與canOpenURL:

UIApplication方法canOpenURL:可以判斷當前設備上是否有能夠響應特定URL的應用。

于是乎,有人利用這個方法過濾大量scheme,判斷設備上安裝了哪些應用。為防止濫用,自iOS9,Apple要求這個方法只能檢測特定名單內的scheme(當然,系統定義的scheme不在此列),開發者需要通過鍵值對LSApplicationQueriesSchemesInfo.plist中定義這個名單。例如:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>alipay</string>
    <string>tencentweibo</string>
    <string>sinaweibo</string>
    <string>weibo</string>
    <string>mqq</string>
    <string>iosamap</string>
    <string>baidumap</string>
    <string>wechat</string>
    <string>weixin</string>
    <string>sinaweibohd</string>
    <string>weibosdk</string>
    <string>weibosdk2.5</string>
    <string>BestPay</string>
</array>

另外,還要注意:

  • 方法canOpenURL:的返回值僅表示當前設備上是否有能夠響應特定URL的應用。并不能反映URL能否被成功處理;
  • 方法openURL:completionHandler:(或openURL:)不受此名單限制;

更多關于LSApplicationQueriesSchemes的信息,詳見Information Property List Key Reference中章節LSApplicationQueriesSchemes的敘述。

參考資料

  1. App Programming Guide for iOS
  2. Apple URL Scheme Reference
  3. Information Property List Key Reference
  4. URL Schemes 使用詳解
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容