iOS Universal Link使用总结

4,874 阅读5分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

以下所有操作步骤已经过实际操作验证

Universal Link通用链接

Universal LinkAppleWWDC上提出的iOS9的新特性之一;能够方便的通过打开一个HTTPS链接来直接启动您的客户端应用,当然前提条件是您必须在手机上安装了此App

Universal Link之前,我们通常使用URL Scheme的方法实现web-App的方式进行跳转;相比于URL Scheme方式,Universal Link提供了极佳的用户体验;

关于更多的介绍,可以查阅Universal Link官方介绍

应用场景

使用Universal Link可以让用户在Safari浏览器或者其他AppWebView中拉起相应的App,也可以在App中使用相应的功能,从而把用户引流到App中;比如我们购物时,在Safari浏览器中进入淘宝网页点击打开手机淘宝则会直接使用Universal Link来拉起淘宝App;

Universal Link优点

  • 唯一性:与自定义的URL Scheme相比,Universal Link使用的是标准的HTTPS协议链接到您的站点,所以一般不会被其他的App所声明;自定义的URL Scheme在没有安装应用的情况下是无法直接打开的,在Safari中还会出现一个不可打开的弹窗;而使用了标准HTTPS协议的Universal Link链接则具备更好的兼容性;
  • 安全:如果用户的手机上安装了您的应用,那么系统回去您配置的网站上下载您上传的文件apple-app-site-association,在这个文件中标明了当前的Universal Link的链接能够打开哪些App;因为只有开发着自己才有权限在网站的根目录上传此文件,所以网站与App之间的关联是安全的;
  • 可变:如果用户的手机上没有安装您的应用,那么不必担心,Universal Link依然能够工作;如果你愿意,在没有安装你的App的时候,用户点击链接,将会在Safari浏览器中展示你网站的内容;
  • 简单:作为Universal Link使用的HTTPS链接,可以同时作用于网站App;
  • 私有:其他App可以在不需要知道你的App是否安装了的情况下与你的App相互通信;

支持条件

  • 比如有一个支持HTTPS的域名,并且拥有该域名下上传文件到根目录(或者是.well-known目录)的权限;需在在根目录(或者是.well-known目录)下上传Apple指定的文件;
  • App开发者网站找到你的App对应的App ID配置Associated Domains,将其勾选上;

  • 在工程中配置:点击+Capability,然后搜索Associated Domains

确定之后,Xcode将会生成如下配置项:

Domains中配置applinks:xxxxxxxxxapplinks:为固定字符串,后边xxxxxxxxx的就是存放文件的网址域名;比如你的网址是https://www.test.com,那么此处只需要配置applinks:www.test.com即可; 需要注意的是DebugRelease两种模式都要配置,Xcode版本不同,可能配置项位置有差异

  • 上传指定文件:创建一个文件,名为apple-app-site-association注意,文件名必须固定为apple-app-site-association,没有后缀,没有后缀,没有后缀;其内容为json格式,如下:
{
    "applinks":{
        "apps":[],
        "details":[
            {
                "appID":"M9N2NBY3KD.com.test.dev",
                "paths":["/qq_conn1/*", "/wechat1/*"]
            },
            {
                "appID":"ZB2D2P7QLR.com.test.dis",
                "paths":["/qq_conn1/*", "/wechat1/*"]
            },

            {
                "appID":"4X3EKPR8EQ.com.apple.dev",
                "paths":["/qq_conn2/*", "/wechat2/*"]
            },
            {
                "appID":"ZB2D2P7QLR.com.apple.dis",
                "paths":["/qq_conn2/*", "/wechat2/*"]
            },
            {
                "appID":"4X3EKPR8EQ.com.thk.dev",
                "paths":["/qq_conn3/*", "/wechat3/*"]
            },
            {
                "appID":"ZB2D2P7QLR.com.thk.dis",
                "paths":["/qq_conn3/*", "/wechat3/*"]
            }
        ]
    }
}

此处我配置了三个App,每一个App测试发布都分开配置,所以出现了六组配置信息;

appID的组成方式为:teamId.your app's bundle identifier;4X3EKPR8EQ、ZB2D2P7QLR、M9N2NBY3KD这些为Team ID,可以在开发者网站找到;

paths为支持的路径列表:/qq_conn3/*QQ分享"/wechat3/*为微信分享使用;

验证

Apple官方提供了验证apple-app-site-association是否配置成的网站前往验证网站

在网站中输入域名(不带协议头),如果出现如下信息,则说明配置成功:

配置失败:

踩坑指南

  • 确认配置apple-app-site-association的网站,美国ip可访问;(十分重要,多次测试,需要美国ip可访问)
  • 确认开发者平台SDK集成Xcode配置项Domains三处Universal Link能够对应;
  • 如果在根目录.well-known目录下同时放了apple-app-site-association要确保两个文件一致(尽量不要这么操作);我最后只在根目录放了文件;
  • 域名需要HTTPS协议;
  • apple-app-site-association文件json数据配置问题:

错误案例1:(/wechat1/后边不是通配符*)

{
    "applinks":{
        "apps":[],
        "details":[
            {
                "appID":"M9N2NBY3KD.com.test.dev",
                "paths":["/qq_conn1/*", "/wechat1/app1"]
            },
            {
                "appID":"ZB2D2P7QLR.com.test.dis",
                "paths":["/qq_conn1/*", "/wechat1/app1"]
            },

            {
                "appID":"4X3EKPR8EQ.com.apple.dev",
                "paths":["/qq_conn2/*", "/wechat2/app2"]
            },
            {
                "appID":"ZB2D2P7QLR.com.apple.dis",
                "paths":["/qq_conn2/*", "/wechat2/app2"]
            },
            {
                "appID":"4X3EKPR8EQ.com.thk.dev",
                "paths":["/qq_conn3/*", "/wechat3/app3"]
            },
            {
                "appID":"ZB2D2P7QLR.com.thk.dis",
                "paths":["/qq_conn3/*", "/wechat3/app3"]
            }
        ]
    }
}

错误案例2:(单独配置了通配符*)

{
    "applinks":{
        "apps":[],
        "details":[
            {
                "appID":"M9N2NBY3KD.com.test.dev",
                "paths":["*", "/qq_conn1/*", "/wechat1/app1"]
            },
            {
                "appID":"ZB2D2P7QLR.com.test.dis",
                "paths":["*", "/qq_conn1/*", "/wechat1/app1"]
            },

            {
                "appID":"4X3EKPR8EQ.com.apple.dev",
                "paths":["*", "/qq_conn2/*", "/wechat2/app2"]
            },
            {
                "appID":"ZB2D2P7QLR.com.apple.dis",
                "paths":["*", "/qq_conn2/*", "/wechat2/app2"]
            },
            {
                "appID":"4X3EKPR8EQ.com.thk.dev",
                "paths":["*", "/qq_conn3/*", "/wechat3/app3"]
            },
            {
                "appID":"ZB2D2P7QLR.com.thk.dis",
                "paths":["*", "/qq_conn3/*", "/wechat3/app3"]
            }
        ]
    }
}

错误案例3:(单独配置了通配符*,并且三个Appq_conn重复)

{
    "applinks":{
        "apps":[],
        "details":[
            {
                "appID":"M9N2NBY3KD.com.test.dev",
                "paths":["*", "/qq_conn/*", "/wechat1/*"]
            },
            {
                "appID":"ZB2D2P7QLR.com.test.dis",
                "paths":["*", "/qq_conn/*", "/wechat1/*"]
            },

            {
                "appID":"4X3EKPR8EQ.com.apple.dev",
                "paths":["*", "/qq_conn/*", "/wechat2/*"]
            },
            {
                "appID":"ZB2D2P7QLR.com.apple.dis",
                "paths":["*", "/qq_conn/*", "/wechat2/*"]
            },
            {
                "appID":"4X3EKPR8EQ.com.thk.dev",
                "paths":["*", "/qq_conn/*", "/wechat3/*"]
            },
            {
                "appID":"ZB2D2P7QLR.com.thk.dis",
                "paths":["*", "/qq_conn/*", "/wechat3/*"]
            }
        ]
    }
}

以上三个json都会导致微信SDK的自检函数WXApi.checkUniversalLinkReady无法通过校验;并且,如果三个App配置在同一个域名下,并且在手机上安装了多个App,那么将会发现分享之后,返回App时返回错误的App;返回的App会根据details中的顺序一次查找,返回找到的第一个App;

正确的json数据格式为:

{
    "applinks":{
        "apps":[],
        "details":[
            {
                "appID":"M9N2NBY3KD.com.test.dev",
                "paths":["/qq_conn1/*", "/wechat1/*"]
            },
            {
                "appID":"ZB2D2P7QLR.com.test.dis",
                "paths":["/qq_conn1/*", "/wechat1/*"]
            },

            {
                "appID":"4X3EKPR8EQ.com.apple.dev",
                "paths":["/qq_conn2/*", "/wechat2/*"]
            },
            {
                "appID":"ZB2D2P7QLR.com.apple.dis",
                "paths":["/qq_conn2/*", "/wechat2/*"]
            },
            {
                "appID":"4X3EKPR8EQ.com.thk.dev",
                "paths":["/qq_conn3/*", "/wechat3/*"]
            },
            {
                "appID":"ZB2D2P7QLR.com.thk.dis",
                "paths":["/qq_conn3/*", "/wechat3/*"]
            }
        ]
    }
}

Universal Link可以为:

QQ:

  • https://www.xxxxxxxx.com/qq_conn/123
  • https://www.xxxxxxxx.com/qq_conn/456
  • https://www.xxxxxxxx.com/qq_conn/789

微信:

  • https://www.xxxxxxxx.com/wechat1/app1/
  • https://www.xxxxxxxx.com/wechat2/app2/
  • https://www.xxxxxxxx.com/wechat3/app3/

按照此处配置,目前微信自检函数完全通过自检;多个App没有出现返回错乱的情况;

Universal Link最终是否配置正确,不能通过分享等功能是否能够成功来判断;因为在Universal Link无法通过校验的情况下分享也有可能会成功,因为此时将会降级使用URL Scheme的方式进行通信;

同理,在Safari浏览器中输入Universal Link,即使出现了App的打开入口,也无法确定Universal Link完全配置正确,因为会出现配置多个App,并且都在手机上安装之后,返回错误的情况;

所以请在测试阶段,以自检函数的检查结果为准;