iOS H5打开App(通用链接)

入秋了,路上会遇到用小贩用小货车拉着卖芒果,和去年一样,我会停下急匆匆的脚步,买几个。一则自己爱吃芒果不过敏,二则品尝下是否和去年一样熟悉的味道。

很多时候可能都希望在浏览器,微信里面点击一个H5链接或按钮,之后直接打开App跳到App里面指定的页面。

  • safari,chrome,UC,搜狗,opera Mini等浏览器-----》唤醒App。
    用户通过浏览器地址栏输入官网地址,或商品地址打开App里面指定页面。若手机内未安装App则引导用户跳入Apple Store下载页。(本来准备举美团的例子,结果美团变成了小程序,那就某东吧)。
    在浏览器中输入商品地址:

手机安装了某东。

2.gif

手机未安装某东。

4.gif
  • 微信,QQ,微博-----》唤醒APP。
    用户通过某APP分享了一条链接至微信,QQ或微博,用户点开该链接后,会引导用户B打开该APP或者下载该APP。

在微信里面点击的分享的商品:

手机安装了某东。

1.gif

手机未安装某东。

3.gif
  • 短信、备忘录,邮件-----> 唤醒APP。
    用户收到一条推广短信,在短信里面点击链接跳入App里面或下载App页。

如何实现上面的场景呢?分为iOS9.0以前和iOS9.0以后。

1.iOS9.0以前只有一种实现方式,scheme方式。若安装App则跳入指定页面,则scheme后面加参数:”taobao://item.taobao.com/item.htm?id=“。若未安装跳到下载页引导用户下载安装。

let link = "taobao://item.taobao.com/item.htm?id=" + id,
    fallback = "itms-apps://itunes.apple.com/cn/app/" + appId;
// 尝试呼起 App
location.href = link;
// 3s 后未能呼起则跳转 App Store
setTimeout(() => location.href = fallback, 3000);

浏览器如何知道手机是否安装了App呢,通过设置延时。

  • setTimeout的实现过程:
    浏览器尝试打开URL scheme并记录时间点t1,在2秒计时后,检查当前时间t2,如果t2-t1 > 2200ms,说明唤起app成功(唤起app会是浏览器的定时器延后执行),如果t2-t1 < 2200ms,可能没有安装app,可以引导用户进入下载页。


    5.gif

    6.gif
var openTime = +new Date();
window.location.href = 'wzry://videolists.show/mark/penta_kill?num=1'
var timer = setTimeout(function () {
    if ((new Date()) - openTime < 2200) {//加了200ms基准误差
        window.location.href = 'you app download page';
    }
    if ((new Date()) - openTime > 2200) {
        clearTimeout(timer);
    }
}, 2000);

  • setInterval实现过程:
    原理上跟setTimeout相似,方法上换成设置一个比较小的时间间隔(例如20ms),运行多次(例如100),比较运行完100次的总耗时与20*100的时间差。逻辑判断同setTimeout。
var limit_num = 100;
var openTime = +new Date();
window.location.href = 'wzry://videolists.show/mark/penta_kill?num=1'
var timer = setInterval(function () {
   if(limit_num > 0){
        limit_num--;
   }else{
        if ((new Date()) - openTime < 2200) {//加了200ms基准误差
            window.location.href = 'you app download page';
        }
        clearTimeout(timer);
   }
}, 20);

iOS9.0以后有两种方式,scheme和universal link(后面单独说)。重要的事情说三遍,iOS9.0以后还是可以用scheme,只是在iOS9上,iframe方案变得不可用,在打开自定义URL scheme时,会弹出对话框,询问是否用 xx应用来打开。若未安装App则会显示“safari打不开该网页,因为网址无效”。(可以通过直接跳转:点击链接或者修改window.location。<a href="schemeUrl">唤醒你的APP</a>,window.location.href = schemeUrl)

针对微信,就不区分iOS9.0之前和之后了,因为微信有白名单,白名单里面只包含50个App的url scheme。怎么查看呢。通过Apple configuration 2能够查到,具体请看文章

白名单如下:在这个 plist 文件中找到白名单很简单,因为微信已经达到了49个的上限,一个很扎眼的 “(49 items)” 的 “Array” 项 LSApplicationQueriesSchemes 就是我们要找的白名单了。我们可以看到诸如腾讯新闻 (qqnews), 腾讯视频 (tenvideo2) 都是在白名单内的。


8.gif

从微信里面打开分享的网页跳入App里面有三种(腾讯应用宝,通用链接,引导用户浏览器打开)解决办法:

1.使用腾讯应用宝。

使用它颁发给你的应用地址,向这个地址跳转,然后一切就交给微信了,直接无视微信什么的,直接带你飞到app内。具体可看腾讯应用宝Applink接入文档。举个例子,网易新闻。从网易新闻分享一天链接到微信,在微信里面点开链接。

  • 若安装了微信。直接打开到网易新闻App对应链接。
7.gif
  • 若未安装微信。腾讯应用宝跳到Apple Store进行下载。有趣的是下载完成后,点击打开后还能跑到对应链接。这是为什么呢。因为在微信里面点击打开按钮时,粘贴板上粘贴了该条链接的信息,跳入网易新闻之后,和淘宝一样监听到粘贴板上面的内容后跳到指定页面。
8.gif
11.gif
12.gif

2.Universal Links(通用链接)。

  • 在2015年的WWDC大会上,Apple推出了iOS 9的一个功能:Universal Links通用链接。如果你的App支持Universal Links,那就可以访问HTTP/HTTPS链接直接唤起APP进入具体页面,不需要其他额外判断;如果未安装App,访问此通用链接时,可以一个自定义网页。

优点:

  • 唯一性:不像自定义的scheme,因为它使用标准的HTTP/HTTPS链接到你的web站点,所以它不会被其它的app所声明.另外,Custom URL scheme 因为是自定义的协议,所以在没有安装 app 的情况下是无法直接打开的,而Universal Links本身是一个HTTP/HTTPS链接,所以有更好的兼容性;
  • 安全:当用户的手机上安装了你的app,那么iOS将去你的网站上去下载你上传上去的说明文件(这个说明文件声明了APP可以打开哪些类型的http链接)。因为只有你自己才能上传文件到你网站的根目录,所以你的网站和你的app之间的关联是安全的;
  • 可变:当用户手机上没有安装你的app的时候,Universal Links也能够工作。如果你愿意,在没有安装APP的时候,用户点击链接,会在safari中展示你网站的内容;
  • 简单:一个URL链接,可以同时作用于网站和app,可以定义统一的web-native协议;
  • 私有:其它APP可以在不需要知道是否安装了的情况下和你的APP相互通信;

缺点:
只支持iOS9及以上系统;当使用Universal Link打开APP之后,状态栏右上角会出现链接地址,点击它会取消Universal Link,需引导用户重新使用Safari再次打开该链接,弹出Safari内置APP广告条,再点击打开重新开启Universal Link。

本来一般公司会有一个官网域名https://www.aaaaa.com/,你必须找运维同学开一个专门用来制作通用链接的域名https://oap.aaaaa.com,然后上传apple-app-site-association的json文件到.well-known和根目录,具体如下面的步骤:

1.创建一个json格式的命名为apple-app-site-association文件,注意这个文件必须没有后缀名,文件名必须为apple-app-site-association上传到https.

{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "ABCD1234.com.aaa.app", 
                "paths": [ "/info/*", "/mobile/*"]
            },
            {
                "appID": "EFGH5678.com.bbb.app", 
                "paths": [ "*" ]
            }
        ]
    }
}

说明: appID = teamId.yourapp's bundle identifier
paths = APP支持的路径列表,只有这些指定的路径的链接,才能被APP所处理,大小写敏感。举个例子,如果你的网站是oap.aaa.com,你的path写的是"/info/*",那么当用户点击www.aaa.com/info/<path>?<params>=<value>,就可以唤醒APP了,相反www.aaa.com/other就不会。此外Apple为了方便开发者,提供了一个网址来验证我们编写的这个apple-app-site-association是否合法有效,这个网址经过测试后有的有效果有的没有效果。下图是输入oia.zhihu.com之后的效果。

WX20181219-193247@2x.png

2.激活Xcode工程中的Associated Domains能力,在其中的Domains中填入你想支持的域名(这里不是随便填的,是可以支持你需要的Universal Links的域名), 必须以applinks:为前缀,例如:applinks:oap.aaaaa.com将会在合适的时候,从这个域名请求apple-app-site-association文件。注意:当你打开Associated Domains后,Xcode会在你的工程中添加.entitlements文件,并且登录开发者中心,可以看到Associated Domains处于Enable状态。

WX20181219-202128@2x.png

3.在AppDelegate里实现如下代理方法:

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {
    // NSUserActivityTypeBrowsingWeb 由Universal Links唤醒的APP
    if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
        NSURL *webpageURL = userActivity.webpageURL;
        NSString *host = webpageURL.host;
        if ([host isEqualToString:@"yohunl.com"]) {
            //进行我们需要的处理
        } else {
            [[UIApplication sharedApplication]openURL:webpageURL];
        }
    }
    return YES;
}

至此APP已经开启Universal Links,可以通过链接唤醒APP,并跳转至指定页面了。流程如下:


WechatIMG433.jpeg

4.跨域。假设当前微信浏览器中话题详情页面的 URL 为 "www.domain.com/XXX",底部“打开App”按钮对应的链接URL为 "www.domain.com/YYY",但由于www.domain.com/YYY不在配置的域名oap.domain.com的域名下,因此实际不能完成跳转。必须写点击事件跳转到与applinks中添加的域名相同的页面例如oap.aaaaa.com/info/download.html(要跨域),在微信中就直接跳转到了我们的app中了!

注:用于跳转打开app的域名需要支持https,如果是一级域名页面有个按钮,点击按钮跳转二级域名来打开app,那么二级域名需要支持https。这里DEMO的二级域名不支持https,所以采用的方案是二级域名跳转到一级域名来打开APP。

5.从微信跳转到app的时候,屏幕右上角还有个 "xxx.xx" 的小箭头:点击该箭头,会在Safari中打开该页面。此时再回到微信浏览器中点击 "打开App"按钮,神奇的事情出现了:无法跳转到app!!!

解决方案:在Safari中打开该页面,将网页拉倒最顶部,会出现一个悬浮框,点击悬浮框中的打开按钮,又跳回到app中打开指定页面,此时再回到微信浏览器中点击 "打开App"按钮,又能正常跳转到app了。
Universal Links 功能的接入其实相当于给某些 URL 添加了一种新的打开方式,但是旧的通过浏览器打开 URL 的方式仍然可用,当点击右上角跳转箭头时,相当于又设置这些特定 URL 的默认打开方式为浏览器而非 web,因此一键跳转功能此时会失效。反之通过点击顶部 "打开" 按钮,相当于又将这些特定 URL 的默认打开方式修改为 app ,一键跳转功能恢复正常。
在Safari中打开页面刚进入时,横条是隐藏的,一定要将页面拉到最顶部时才能显示。

3.引导用户去浏览器打开。微信已经屏蔽了通用链接,所以大多数App都做了引导用户去浏览器打开。下一篇文章介绍微信屏蔽通用链接

4.gif

推荐阅读更多精彩内容