iOS9 Universal Links踩坑之旅,移动应用之deeplink唤醒app

目录

一.URL Scheme
二.通过meta标签打开app
三.Universal Links简介
    · Universal Links的相关配置
四.小结
    · Universal Links的配置都是干啥用的
五.如何实现微信拦截Universal Links的效果
六.评论区问题汇总

简单粗暴,有一个需求:


  • 用手机打开我们的网站,点击打开按钮或者收藏按钮,用户如果已经安装app,跳转到app做相应的操作。
  • 如果没有安装app,则跳转到应用商店提示用户下载安装。

方法1: URL Scheme


    holy 个 shit 啊,第一时间想到的是url scheme ,然后将参数配置在url scheme后面,唤醒app再进行页面跳转逻辑。

    但残酷的现实是企鹅和微信都把url scheme 唤醒app这种方式给禁了。

方法2: meta标签


    然后考虑了在网页上对meta 标签做手脚,可以实现类似下图的效果:

meta标签示例.jpeg

meta标签的格式如下:

 <meta charset="UTF-8" name="apple-itunes-app" content="app-id=1234567890, affiliate-data=myAffiliateData, app-argument=yourScheme://">

    这样添加meta标签后的网页,使用safari打开的时候,就会在顶部显示自己app的导航条。
    如果没有安装app点击能够跳转到appstore去下载,如果安装了app就能直接通过顶部的meta标签唤醒app了。

方法3:Why Universal Links?


    上面两种方式都能实现某一方面的需求,但无法完美解决。于是就想到了iOS9之后的Universal Links。

什么是Universal Links呢?

    Universal Links就是一个通用链接,iOS9以上的用户,可以通过点击这个链接无缝的重定向到一个app应用,而不需要通过safari打开跳转。

    如果用户没有安装这个app,则会在safari中打开这个链接指向的网页。

如何支持Universal Links呢?

    按照苹果官方文档来说,支持通用链接非常简单哟,只需要三步呢

1.创建一个名字叫做apple-app-site-association,包含固定格式的json文件

2.将这个文件上传到你的服务器,可以将这个文件放到服务器的根目录下,也可以放到.well-known这个子目录下。

3.配置app,然后在app里面添加代理方法

    如果已经配置过Universal Links,那么在用户第一次安装app时,苹果会发送一个请求,请求你服务器上的apple-app-site-association文件。

    请求apple-app-site-association文件成功之后,用户就可以使用Universal Links唤醒app了。

详细的配置流程如下


(1) 关于apple-app-site-association文件的配置

{
"applinks": {
        "apps": [],
        "details": [
            {
                "appID": "teamID.bundleId",
                "paths": ["/deaplink","/wwdc/news/","*"]
            },
            {
                "appID": "ABCD1234.com.apple.wwdc",
                "paths": [ "*" ]
            }
        ]
    }
}

    创建一个包含上述格式的json文件,文件名字必须为apple-app-site-association,不能带后缀名,有的电脑设置的隐藏后缀名,这点需要注意。

appID

    appID 的 格式为 teamID.bundleId形式。

如何获取teamID呢?

    登录开发者网站 ,找到Membership选项卡。

teamId.png

    譬如说我的teamIDxxxxxxxxxxxbundleIdcom.mytest.app
    那么我的appID就是:xxxxxxxxxxx.com.mytest.app

paths

    paths配置,实际上就是限制哪些路径可以唤醒app,哪些路径不能唤醒app。格式如下:

"paths": [ "/wwdc/news/", "NOT /videos/wwdc/2010/*", "/videos/wwdc/201?/*"]
  • 使用*配置,则整个网站都可以使用

  • 使用特定的URL,例如/wwdc/news/来指定某一个特殊的链接

  • 在特定URL后面添加*,例如 /videos/wwdc/2015/*, 来指定网站的某一部分

  • 除了使用*来匹配任意字符,你也可以使用 ?来匹配单个字符,你可以在路径当中结合这两个字符使用,例如 /foo/*/bar/201?/mypage

需要注意的是:
配置的paths路径,是区分大小写的

验证apple-app-site-association文件

    文件配置完成之后,将其上传到你的服务器根目录或者.well-known这个子目录下。

  • 确保使用https://yourdomain.com/apple-app-site-association这个链接可以访问到,yourdomain.com为你的服务器域名。
  • 也可以使用苹果的验证网站,验证文件是否能被苹果请求到。如果是未上线的应用,使用验证网站时可能出现如下提示:
Validation Tool.png
  • 出现该提示为apple-app-site-association文件配置正确。
  • 出现404错误码提示,则为apple-app-site-association文件未上传成功,或者使用https://yourdomain.com/apple-app-site-association路径无法访问。

(2) 建立web网页和app应用之间的关联 -> app IDs 配置 和 项目配置

app IDs 配置

    进入开发者网站,找到你自己的bundleId,可以点击edit按钮,开启associate domains,如下图:

associated domains.png

项目配置

    在项目的Capablities中开启Associated domains,如下图:

appLinks.png

    注意domains可以添加多个,前缀必须为applinks:applinks:后为你的服务器的域名。

代码接收Universal Links唤醒

-(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler{

    NSLog(@"userActivity : %@",userActivity.webpageURL.description);
    return YES;
}

    在appdelegate中实现上面这个方法,当使用Universal Links唤醒app时就执行这个方法。

(3)验证以上配置

    快捷验证,在备忘录中输入https://yourdomain.com/apple-app-site-association,长按这个链接,出现下图提示则配置成功。

successful.png

某些坑


  • 服务器必须要支持https,而且需要支持TLS1.2协议以上,不过相信苹果强制支持https之后,这个坑就会慢慢填上了。现在还有很多童鞋的服务器使用的免费的证书,或者证书不被苹果信任,然后就会导致无法下载apple-app-site-association。苹果支持的https根证书列表
  • 只支持iOS9以上
  • apple-app-site-association文件名千万不能写错啊
  • 使用charles抓包显示,只有初次安装app时才会去请求apple-app-site-association文件,所以测试时有可能因为网络波动导致apple-app-site-association文件获取失败。这种情况,多卸载几次,安装时使用4G。
  • 验证各种配置的还有一个网站,需要打成ipa包丢上去。

小结一下


    Universal Links的配置总结起来很简单:

  • 去开发者网站配置appid,找到teamid
  • 创建一个没有后缀名的apple-app-site-association文件,填写相应的配置
  • 配置项目,并编写相应的唤醒处理逻辑
    但是为什么要配置这些东西呢?配置他们的目的分别又是什么呢?我们换个角度来考虑一下

    先来看一下审核条款中的一项规定

  2.5.6 Apps that browse the web must use the appropriate WebKit framework and WebKit Javascript.

=͟͟͞͞( •̀д•́) app 浏览网页使用的都是苹果的WebKit哟。

    而Universal Links之所以可行,也正是因为 WebKit。运行在iOS上的所有app,当他们使用 WebKit 打开某一个链接时,WebKit 肯定是能拦截到的。

    那么,Universal Links相关配置的作用就非常明了了。

Q:appid和项目中为什么要配置支持associate domains呢?
A:为了在app启动的时候告诉系统,我这个app支持Universal Links呀,这样系统才方便根据项目中配置的domain域,去下载apple-app-site-association文件呀。

Q:apple-app-site-association文件配置了一堆是干啥用的呀?
A:作为WebKit加载链接时进行拦截,然后跳转到目标app的配置文件呀。

如何在自己的app里实现微信屏蔽Universal Links的效果?(2018-07-27更新)


    我们先来看一下UIWebview的代理方法。
    以知乎为例,在下面的代码里判断如果是知乎的Universal Links链接 ,就不再加载。
    这种方法适用于白名单类型的加载,只要不在名单里面的全部干掉。

  - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    
      NSString *requesUrl = request.URL.absoluteString;
    
      if ([requesUrl containsString:@"oia.zhihu.com"]) {
          return NO;
      }else{
          return YES;
      }
  }

    而iOS微信浏览器对于Universal Links的拦截并不是这样,微信拦截的是Universal Links唤醒其他app的动作,而并不会将Universal Links指向的网页加载拦掉。

    iOS微信浏览器内核是基于WebKitWKWebview ,在WebKit中,有两个公开的控制是否加载某个链接的WKNavigationActionPolicy枚举:
    - WKNavigationActionPolicyCancel
    - WKNavigationActionPolicyAllow

    除此之外,还有一个私有的枚举_WKNavigationActionPolicyAllowWithoutTryingAppLink,且

  _WKNavigationActionPolicyAllowWithoutTryingAppLink = WKNavigationActionPolicyAllow + 2;

    那么我们在app里面拦截Universal Links的唤醒行为就非常简单了,同时不会对Universal Links指向网页的加载造成影响。

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    
    NSString *requesUrl = navigationAction.request.URL.absoluteString;
    
    if ([requesUrl containsString:@"oia.zhihu.com"]) {
        decisionHandler(WKNavigationActionPolicyAllow + 2);
    }else{
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

    这是demo,如果有兴趣,还可以深入研究一下这个私有类LSAppLink
    参考链接

2017年9月14日更新----评论区问题汇总


  • 按照上面写的配好了,怎么死活打不开呀???

    1.支持https呀,一定要是符合苹果认证的https证书呀。

    2.系统问题,确保iOS9以上

    3.配置文件问题,apple-app-site-association文件中配置的path和测试用的通用链接不一致,注意是区分大小写的。

    4.域名问题,xcode中配置的域名一不小心写错了。

  • 为毛有的手机成功了,有的手机就不行呢???

    1.上面也提到过,因为网络波动有可能会导致部分用户第一次安装时,无法下载apple-app-site-association文件,这个只能引导用户删除重装或者在迭代时修改Associated Domains配置告诉系统重新下载apple-app-site-association文件。

    2.另外一种可能是苹果抽风导致,笔者今年年初一碰到过一个蛋疼的问题,从中午一直到下午4点发现重复的删除重装,app也不会请求服务器的apple-app-site-association文件,过了4点之后就好了。当时因为时间特殊并没有深究到底是什么原因导致。

  • 服务器换域名了肿么办???

    笔者做了一个小测试,当Associated Domains添加新的 Domains的之后,在app再次启动的时候抓包发现(不需要删除重装),苹果会给新添加的这个Domains发送一个请求,请求新Domain下的apple-app-site-association文件。

    也就是说Associated Domains发生改变的话,系统是会知道的,这样就可以在迭代的时候删除旧的域名,添加新的域名了。
    另外Domains的配置也可以使用通配符,例如:applinks:*.mywebsite.com

  • 全都配置好了,项目也能唤起来了,web页面到底该怎么弄呀???通用链接指向的服务器的页面到底应该是哪个?

    我们之前iOS和安卓用的是同一个网页,也就是说从app内分享出去的网页,可以被苹果用户和安卓用户同时查看,在这里我们是由web童鞋使用js判断当前所处的平台以及其系统。

    如果是安卓用户,则显示安卓相关提示页面。

    如果是苹果用户,那么分两种:

    1、如果是9以上的系统,相关的“在app内打开”按钮的链接配置的就是我们的通用链接Universal Links了,且该通用链接地址指向的是一个 app下载引导页面,那么当用户安装了app,即可通过通用链接唤醒app;如果用户没有安装app,那么就会跳转到通用链接指向的app下载引导页面,达到最大化的客户导流。

    2、如果是9以下的系统,则由web童鞋在当前页面添加一个 “右上角在safari打开”,相应的 “在app内打开”的按钮就会发一个 跳转到我们app schema的重定向,以实现在safari中唤醒我们的app。

  • 当使用通用链接唤醒app之后,手机右上角有一个小按钮?

    那个小按钮是可以引导用户跳转到safari中,名字叫bread crumbs button(面包屑),当然也去不掉。

  • 备忘录和safari中都可以打开app,怎么分享到其他app里面就不行了?

    未跨域导致的,如:分享到微信的链接是 https://www.mydomain.com/share.html,然后该网页中的“在app内打开”按钮配置的通用链接为 https://www.mydomain.com/index.html
    跨域的意思是说,通用链接 和 调用通用链接的网页不要使用同一域名。
    即如果通用链接域名为“www.mydomain.com”,则通用链接所处的网页域名就不能是“www.mydomain.com”。

  • 欢迎大家在评论区继续互动呀,私信不好一起玩耍呀。

参考链接:
    1.大招之 官方文档
    2.不错的博文
    3.苹果验证通用链接是否可用的网站
    4.通用链接文件存放的server需要支持https 苹果支持的https证书列表

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,757评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,478评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,540评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,593评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,903评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,329评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,659评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,383评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,055评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,337评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,864评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,227评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,820评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,999评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,750评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,365评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,260评论 2 258

推荐阅读更多精彩内容