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阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容