iOS Universal Links踩坑之旅

20191031关于Universal Links appID的取值说明,见下面文章内容


自从微信7.0.5版本放开 Universal Links之后,就把这种无缝唤醒App的方式提上日程了(主要是遇到每一个测试都要解释一下schemes的缺点,太烦了)。通过链接跳转到App应用内部页面,目前iOS主流的方案有两个:

  1. URL Schemes
  2. Universal Links

需求

如果手机中有安装App则跳转到App内部页面,没有安装App的话,则应跳转到App Store下载页面或指定页面。

URL Schemes

URL Schemes是iOS9之前比较主流的一种跳转方案了,更多的是用在了两个App相互跳转中。也可以在Safari中输入Schemes://跳转到App内部。 例如weixin://

但是这种方式很不顺滑,在每次跳转的时候都会弹框询问。如果iPhone中如果没有安装则会直接弹出错误提示(这也是每次测试说这个是缺陷的时候我要解释N遍的苦恼),而且微信也封了这种跳转,现在微信放开Universal Links就赶紧开干。

Universal Links

如果英文棒棒哒的话建议直接看官方文档 Support Universal Links

Universal Links(通用链接)是iOS9.0出的新技术。如果我们的应用支持通用链接,那么我们就可以无缝的链接到App内部,流畅的跳转体验,简易的接入方式,同时又解决H5Native间的无缝切换;对于应用层面,站外引流效率提高(手机中没有安装此App),转化率提高等等。
从iOS 9.2开始,在相同的domainUniversal Links是不work的,必须要 跨域 才生效,实测值需要跨子域名即可,比如 m.domain.com 跳转 o.domain.com 是可以触发跳转App

使用条件
1.有一个注册的域名。
2.支持https请求,并且CA证书是有效的
3.能够上传文件到自己的域名(一个名为apple-app-site-association的json格式文件)
4.Xcode7, iOS 9以上,并且在Xcode项目中做好适配
1.准备接入工作
  • 首先是将项目中CapabilitiesAssociated Domains打开,并填上你的域名,前缀是applinks。如果你的域名是mywebsite.com,则填上applinks:mywebsite.com(如图1)。
    App会在第一次启动的时候通过填写的域名来下载apple-app-site-association文件,该文件会在接下来说明。

    图1

  • 配置后会发现项目中多了一个APPNAME.entitlements文件(如图2)

    图2

  • 然后去开发者中心当前证书下打开Associated Domains开关,并更新一下证书

    图3

  • 同时把Team ID记录下来,下面会用到

    图4

2.创建apple-app-site-association文件

创建一个apple-app-site-association文件(注意是没有后缀的),其内容是json格式,官方示例如下

{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "9JA89QQLNQ.com.apple.wwdc",
                "paths": [ "/wwdc/news/", "/videos/wwdc/2015/*"]
            },
            {
                "appID": "ABCD1234.com.apple.wwdc",
                "paths": [ "*" ]
            }
        ]
    }
}
特别需要注意:(这个坑搞了我好几天,最后发现还是官方文档靠谱)

The value of the appID key is the team ID or app ID prefix, followed by the bundle ID. (The appID value is the same value that’s associated with the “application-identifier” key in your app’s entitlements after you build it.)

appID 的 格式为 teamID.bundleId或者app ID prefix.bundleId形式,切记不要搞错!!很多文档只是说teamID,但是官方文档是说team ID or app ID prefix,不知道用哪个的时候你可以把你编译之后的包解压看看embedded.mobileprovision文件里面的application-identifier值是什么就用什么。
比如说我的teamID9JA89QQLNQbundleIdcom.apple.wwdc那么我的appID就是:9JA89QQLNQ.com.apple.wwdc

paths的配置,实际上就是限制哪些路径可以唤醒App,哪些路径不能唤醒App,其中 * 表示任意路径

3.上传apple-app-site-association文件

apple-app-site-association文件保存的位置

4.检查配置文件是否正常

1.使用浏览器打开我们上传的文件路径,应该可以直接看到刚刚上传的json文件。
https://mywebsite.com/apple-app-site-association
或者
https://mywebsite.com/.well-knowna/apple-app-site-association

坑1:注意:这里在浏览器打开应该是可以看到json格式的文件内容,在这里被坑好久,如果不是,则要修改此文件服务器的返回格式 修改nginx返回json或者文本格式详解

2.苹果也提供了一个官方网页供我们开发者来验证自己的网页配置是否有效。
验证地址:App Search API Validation Tool

3.终极办法-使用Charles进行抓包查看有没有下载

5.如果第四步没问题就可以编译App来检查

坑2:clean一下Xcode再跑,不然有时候Xcode抽风了你还以为是服务器配置错了
坑3:如果你配的是applinks:www.mywebsite.com则要用这个链接唤醒:https://www.mywebsite.com/.well-knowna/apple-app-site-association
如果你配的是applinsk:mywebsite.com则要用这个链接唤醒:https://mywebsite.com/.well-knowna/apple-app-site-association,切记切记!

在备忘录输入你配的对应域名,点击可直接跳转到App,长按会显示(在“AppName”中打开)。


图5

这样就成功啦!

问题汇总:

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

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

  • 在项目的 AppDelegate 里实现回调方法
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler
{
    if ([userActivity.activityType   isEqualToString:NSUserActivityTypeBrowsingWeb]) {

      NSURL *webpageURL = userActivity.webpageURL;
      NSString *host = webpageURL.host;

      if ([host isEqualToString:@"xxxx.com"]) { 
        // 解析路径、跳转到指定界面 and so on...
    }
    else {
      [[UIApplication sharedApplication]openURL:webpageURL];
    }
  }
  return YES;
}

扩展阅读:
Universal Link(iOS)踩坑

推荐阅读更多精彩内容