本文首发于:https://github.com/bigo-frontend/blog/ 欢迎关注、转载。
基于短信场景一键唤起app技术原理解剖
场景
多数APP的卸载量在提高,各家面临的情况大同小异。流失的用户需要召回,短信引流是相对有效的方式之一。
产品要求:
- 在短信中放入链接,用户点击链接如果用户已安装app则直接唤起app(且不需要经过浏览器),如果用户未安装app则打开浏览器显示app下载页面。
- 链接需要尽可能的短(短信有字数限制,超出长度按多条收费)
相关技术
一、web唤起app技术
web调起app技术常见的有三种 URL Schema,universal link(ios), app links(android);经调研 URL Schema无法在短信中调起app,universal link 和 app links可以。下面详细介绍下三种技术。
1.URL Scheme
首先解释下scheme,我们看URL的组成:
[scheme:][//authority][path][?query][#fragment]
拿 https://www.baidu.com 来举例,scheme就是https,也就是url的开头部分来定义url的类型。我们可以通过给app分配一个指定scheme开头的url,通过这个url可以在浏览器中直接唤起app的某个功能。
常见app的URL Scheme
微信 | 支付宝 | 淘宝 | 微博 |
---|---|---|---|
weixin:// | alipay:// | taobao:// | sinaweibo:// |
缺点:
- 当要被唤起的app没有安装时,点击这个链接会报错,而且在不同的手机里报错的表现形式各种各样。
- 假如多个app注册了同个scheme,web端是无法区分的,会弹出一个弹窗让用户选择打开哪个app
- 基本上只能在浏览器中使用,多数app内webview中是无法使用的,比如微信
- 无法判断app是否已安装从而执行打开app还是下载app逻辑,只能通过hack方式勉强达到效果
2. universal link
universal link是苹果在ios 9后推出的通用链接技术,前端可以通过访问普通的https链接打开app,如果未安装app会正常访问https链接内容。
优点:
- 对于用户安装和未安装app的情况表现非常丝滑,有安装直接打开app,未安装正常访问网页内容(通常我们会将链接指向下载页)
- 链接唯一性,不会存在一个链接对应多个app的情况,因为universal link有一步通过服务器校验可以保证唯一性。
- 生效场景多,因为这个是系统的功能,所以不限定于浏览器。短信里也能生效(这个不就是我们想要的么)
贴图说明下universal link的业务使用流程
3.app links
app links是android 6.0后推出的技术,功能和universal link类似,这里不细说了。
三者对比
二、链接尽可能的短
1.使用短链服务(不可行)
让链接尽可能短,我们很容易想到使用短链服务。短链服务是指,我们输入一个长链接短链服务会返回一个比较短的链接给我们使用。我们访问短链接的时候会重定向到我们的原始长链接。 但是这种服务不适合我们的场景,我们使用了universal link 和 app links,这两种技术都要求在域名根目录能访问到指定的配置文件。使用短链服务的时候,短链根域名下并没有对应的配置文件,实现不了直接唤起app的功能。
2.申请短域名并配合运营后台
为了实现跳转到app不同的功能,我们一般会在链接后面拼接参数来指定具体的功能场景,这样一来整个链接就会比较长。
- 为此我们实现一个运营后台,由运营配置具体参数,然后生成一个短id,链接上面只带这个短id,app通过这个短id读取运营后台配置再得到具体的参数
- 申请一个短的域名
- 短信里链接不带协议头https
最终链接形式如: z.short.com/5f2ac8dd
具体实现
我们梳理下整体流程
- 运营后台配置具体参数,生成短id如5f2ac8dd
- 短信发送链接 z.short.com/5f2ac8dd
- ios采用universal link , android采用 app links实现点击短信链接,如用户已安装app直接唤起app,如用户未安装app唤起浏览器显示app下载页
- 为兼容低版本不支持universal link 和 app links的手机,web下载页使用URL Scheme技术兜底,点击下载时尝试再次唤起app
1. 运营后台实现
这个就是普通的保存配置功能,根据app需要的参数自行设计表结构,最终生成一个标识id供app查询具体参数。
2. universal link
- 域名需要支持https
- 在域名根目录上传apple-app-site-association文件,内容为json格式
{
"applinks": {
"apps": [],
"details": [
{
"appID": "你的TeamID.你的Bundle ID",
"paths": ["/*"]
}
]
}
}
主要配置
appID:让app同事提供
paths:配置指定的路径,这些路径才会唤起app功能,支持使用通配符
前端需要处理的到这里就结束了,客户端的处理有兴趣的可以搜下客户端的处理。
注意点:
- Universal Link必须要求跨域,如果是网页A中触发调整universal link B,则A和B必须是不同域名
- Universal Link请求apple-app-site-association时机是在app第一次安装运行的时候,如果更新了apple-app-site-association,需要app升级旧用户才会生效。
3.app links
- 域名需要支持https
- 在根域名.well-known目录下上传assetlinks.json文件,内容如下
[
{
"relation": [
"delegate_permission/common.handle_all_urls"
],
"target": {
"namespace": "android_app",
"package_name": "com.ss.android.ugc.aweme",
"sha256_cert_fingerprints": [
"D7:81:1E:C4:16:6F:EA:6C:C7:20:BA:66:69:9D:C8:4B:58:4A:C9:E6:98:66:13:A7:6D:4E:43:D8:CB:E3:2B:27"
]
}
}
]
relation 可以指定哪些path可以唤起app,其它内容让客户端同事提供
4 z.short.com/5f2ac8dd 访问到web下载页
因为单独申请了个域名做短信召回功能,所以可以不考虑其它扩展将所有访问不到的链接全部解析到下载页,能访问到的静态资源正常访问。
这里直接使用try_files指令配置nginx
nginx location配置如下
location / {
try_files $uri $uri/ /download.html;
}
对try_files指令的解析:
这个指令功能是这样,在收到访问请求的时候,先测试$uri是不是文件,再测试是不是目录,如果是继续访问,如果不是,则调用内部的重定向指令,在这个配置里是重定向到/download.html
5. web下载页使用URL Scheme技术兜底
点击下载尝试唤起app,如果没唤起app,则进行下载。我们无法判断app是否被唤起,换个hack思路实现下。
当app被成功唤起时,我们的web页面会变成隐藏状态,假如执行唤起3秒后我们的页面不处于隐藏状态我们就认为没有成功唤起app,执行下载逻辑,代码实现如下
function openApp(deeplink, downloadUrl) {
window.location.href = deeplink;
setTimeout(() => {
const isHidden = document.hidden || document.webkitHidden;
if (typeof isHidden !== 'undefined') {
if (!isHidden) {
window.location.href = downloadUrl;
}
} else {
window.location.href = downloadUrl;
}
}, 3000);
}
结语
短信召回用户的相关内容就讲完了,希望对碰到这种业务场景的同学有所帮助
欢迎大家留言讨论,祝工作顺利、生活愉快!
我是bigo前端,下期见。