「福利」 ✿✿ ヽ(°▽°)ノ ✿:文章最后有抽奖,《JavaScript 高级程序设计 - 第四版》,走过路过不要错过哦

转转 App 是我们公司最核心的产品,引导用户到转转 App 中来,对用户增长和留存十分重要。常见的做法是在各个流量入口,投放 Web 版的引流页面,然后通过该页面唤起 App(下文简称「唤端」)。本文重点介绍转转是如何在各种场景下,完成整个唤端流程的。

唤端功能架构

我们先通过一张 Gif 图,直观的看下唤端是什么如上图,在 Safari 浏览器中,当我们点击唤起 App 按钮后,系统提示我们是否需要 “在转转中打开”,点击确认后,转转 App 便被唤起来了,这就是一个最简单的唤端场景。

不过细心的同学一定会问,那如果我系统没装转转 App,点击按钮会是什么效果呢?
这是一个很常见的场景,对于没有安装相关 App 的用户,往往会需要跳转到下载页面,让用户去下载。

也就是说唤端一般包含了 「唤起 App」「下载 App」 以及 「唤起 App 失败后自动下载」 这三个功能。

再进一步想一下,唤端功能还需要能唤起指定页面,比如一个用户在下单页,唤起 App 后,我们希望 App 默认打开的还是那个下单页,不然让用户再走一遍流程到下单页,那对订单转化率会有不小的影响。

总结一下,我们用一张流程图来说明下唤端整体功能架构

唤端技术架构

聊完了唤端是什么,接下来进入主菜,聊聊唤端具体的技术架构
唤端所使用的技术,通常可以统称为 Deep Link(深度链接)技术。不同平台对这项技术有着不同的实现,主流的有这几种

  • URL Scheme(全平台通用)

  • Universal Link(通用链接,iOS 系统专属)

  • App Links 以及衍生的 Chrome Intents(安卓系统专属)

当然,以上只是国际通用标准,我们还需要考虑到“国内特色”,包括但不限于「微信爸爸」、微博、UC 浏览器等这些环境的唤端,对于这些 App,主流的唤端方式有这么几种

  • Universal Link(部分 App 可用,快被国内主流 App 禁干净了)

  • 微信 API launchApplicationgetInstallState (需要申请白名单,难度很高)

  • 微信开放标签 <wx-open-launch-app> (微信推荐方式,需要审核,流程较繁琐)

  • 跳转到应用宝,然后通过应用宝唤端 (适用于微信安卓环境)

  • 弹出个蒙层,友好的提示用户,点击右上角按钮,然后选择在浏览器中打开 (easy~)

看过去有点天花乱坠,老样子,我们通过一张功能架构图,完整的看看唤端的技术架构怎么样,看完了功能架构图是不是更晕了 ????,别着急,接下来我会针对上面提到的主要方法进行细致的讲解。

常见唤端方法详解

这部分,我们主要介绍下 URL SchemeUniversal Link微信唤端自家公司App 四种技术场景下的唤端实现

URL Scheme

URL Scheme 其实就是一个 URL 前面的协议部分,比如这个地址 https://m.zhuanzhuan.com,其中 https就是一个 Scheme,代表这是一个https的地址。

我们再看一个地址 zhuanzhuan://jump/core/myBuyList/jump?tab=0,当我们访问这个地址的时候,如果系统中有注册 zhuanzhuan:// => 转转App,那么系统便会使用转转 App 打开这个链接了,接着 App 会解析 URL 的 path 和 search 部分,执行对应的操作。

那么如何向系统注册 zhuanzhuan 这个 Scheme 呢,安卓可以在 manifest 里通过 intent-filter 配置,iOS 则可以在 info.plist 文件中添加 URL types 来注册一个 Scheme。

Scheme 的调用方法

Scheme 的调用也十分简单,我们可以通过 location.hrefiframea标签 来调用。
这三种方式并无本质区别,都是让系统访问一个 URL,只不过在某些环境下,当方法失效时,需要采用另一种形式。

经过长时间的摸索,我们总结了如下最佳实践

  • 在 iOS 的 QQ 环境,使用 a标签 方式调用 URL Scheme 更加稳定

  • 非上述情况,使用 location.href 调用 URL Scheme 即可

  • 如果希望 URL Scheme 出错时,唤端不会跳转到错误页面,那么可以使用 iframe 的形式,不过需要注意个别机型的兼容性

三种调用方式的具体代码如下

// SCHEMA_PATH 为 URL Scheme 地址// location.href 形式
window.top.location.href = SCHEMA_PATH;// a标签形式
const a = document.createElement("a");
a.setAttribute("href", SCHEMA_PATH);
a.click();// iframe形式
iframe = document.createElement('iframe');
iframe.frameBorder = '0';
iframe.style.cssText = 'display:none;border:0;width:0;height:0;';
document.body.append(iframe);
iframe.src = SCHEMA_PATH;

唤端失败自动下载

使用 URL Scheme 会遇到一个棘手的问题,那就是我们无法得知是否成功唤起 App。这个也可以理解,因为这个方式本质上就是访问一个 URL,并没有特别的地方。
但是唤端失败(通常是用户没有装这个 App),我们需要引导用户去下载,这就要求我们需要通过一些手段,去检测唤端是否成功。
常见的做法是通过监听页面是否在 n 秒内 隐藏来判断是否成功唤起 App,因为如果唤起,那当前页面必然已经退到后台去了。

所以我们处理的流程是这样

  1. 当点击唤端后,定时器延时 n 秒(我们设定的是 2.5 秒)后执行下载操作

  2. 监听 visibilitychange 事件,如果页面隐藏,则表示唤端成功,清除定时器

  3. 如果 visibilitychange 事件没有被触发,那么就代表唤端失败,n 秒后就会执行下载的操作

具体代码如下

// n秒后执行下载
const timer = setTimeout(() => {this.__download(options);
}, options.delay);// 页面隐藏,那么代表已经调起了app,就清除下载的定时器
const visibilitychange = function() {const tag = document.hidden || document.webkitHidden;tag && clearTimeout(timer);
};document.addEventListener("visibilitychange", visibilitychange, false);
document.addEventListener("webkitvisibilitychange", visibilitychange, false);
window.addEventListener("pagehide",function() {clearTimeout(timer);},false
);

不过这个方法有个致命问题,就是 n 应该取多少,不同的手机,唤端的时间并不一样。

  • 时间设置太长,用户下载等待太久,会导致用户还没看到下载就退出了。

  • 时间设置太短,可能会导致还没有唤起 App,就又同时执行了下载的逻辑。

这里我们经过测试,觉得 n 设置为 2500ms-3000ms,是一个比较合适的值

URL Scheme 在 iOS 上的问题

上面说到了唤端失败自动下载的场景。在实际项目中,我们会发现在 iOS 上使用 URL Scheme 还有一个问题,就是即执行了唤起,也执行了下载。经过测试我们得到了如下流程

  1. 用户点击唤端按钮(记录 Time1)

  2. Safari 弹出是否在“转转”打开的 confirm 框

  • 此时虽然弹出了 alert 框,但是并未阻断代码运行,所有代码仍在运行中,只是界面没变

  • 用户点击打开转转(记录 Time2),跳转到转转

  • 用户返回 Safari,如果 Time2 - Time1 的时间大于设置的时间 n,那么之前的逻辑代码便会继续运行。也就会出现唤端成功后,又继续走下载逻辑

  • 对于这个问题,大家看这个动图更直观些,第一次是点击唤端后,停留了一会才点击打开。第二次是立刻点击打开

    Universal Link

    上面提到了 URL Scheme 在 iOS 的一些问题。其实在 iOS 系统中,有一种更好的方式,那就是接下来要介绍的 Universal Link。
    Universal Link 是在iOS 9中新增的功能,使用它可以直接通过https协议的链接来打开 APP。
    同时因为是使用https协议,所以如果没有唤端成功,那么就会直接打开这个网页,不再需要判断是否唤起成功了。并且使用 Universal Link,不会再弹出是否打开的弹出,对用户来说,唤端的效率更高了。

    我们先看一个 Universal Link 唤端的例子,比如这个地址 https://mjump.zhuanzhuan.com/zhuanzhuan/index.html,直接访问它是一个下载引导页,但是在项目中,通过 location.href 跳转,却可以直接唤起转转。
    PS:点击按钮时,执行的代码是 location.href = https://mjump.zhuanzhuan.com/zhuanzhuan/index.html

    Universal Link 的配置过程,网上的文章比较零散细碎,这里我梳理下它的原理与关键点,把流程串起来,方便理解,避免大家采坑

    1. app 在发布的时候,在Associated Domain配置好一个域名

    • 该域名与今后要唤端页面的域名,不能一样。比如 转转 web 的域名是 m.zhuanzhuan.com,那么这个域名就不能用它了,可以用 mjump.zhuanzhuan.com

  • iOS 系统在「app 安装」的时候,会请求配置在Associated domain中域名(在这里就是https://mjump.zhuanzhuan.com)的根路径或者.well-known路径的配置文件apple-app-site-association,并把它注册到系统中

    • 这个文件的内容大体如下,其中 appID 就是 App 在系统中的 id,paths我们后面会提到

    {"applinks": {"apps": [ ],"details": [{"appID": "ECVV5G85CD.com.wuba.zhuanzhuan","paths": ["zhuanzhuan/*","/qq_conn/1104903352/*"]},{"appID": "ECVV5G85CD.com.zhuanzhuan.yige","paths": ["yige/*"]},{"appID": "75BF75R4NH.com.wuba.*","paths": ["*"]}]}
    }
    
    1. 当页面进行「跨域访问」时,比如从https://m.zhuanzhuan.com跳转到https://mjump.zhuanzhuan.com/zhuanzhuan/index.html,因为mjump.zhuanzhuan.com在第 2 步的时候,已经被系统注册过了,所以系统会把页面的 path,也就是zhuanzhuan/index.html部分,和上面的配置文件中的 paths 进行匹配,如果能匹配上,那么就会唤起配置文件中对应的 App。如果匹配不上,或者用户没有安装该 App,那么就正常进行地址访问

    • 因为唤端失败会访问https://mjump.zhuanzhuan.com/zhuanzhuan/index.html地址,所以这个地址不能是 404

    • 直接在浏览器访问这个地址,并不会唤起 App,因为不是「跨域访问」

    • 唤起 App 后打开指定页面,可以通过在 URL 上增加参数,然后 Native 解析参数的形式来实现

    微信唤端

    微信作为一个超级 App,如果能借助微信的流量进行唤端,想想也很开心 ????。不过微信对唤端做了十足的限制,用起来可没有那么容易

    微信通用唤端能力

    微信7.0.5版本放开了 Universal Link,所以在 iOS 系统下,使用 Universal Link 就可以在微信完成唤端。
    在实际使用中,我发现了一个奇怪的问题,就是有些 App 可以在微信直接唤起到另一个 App,中间没有任何提示。而转转在唤端的时候,会有一个“可能离开微信,打开第三方应用”的提示 ????

    在安卓端,我们可以使用应用宝进行微信唤端。先跳转应用宝,然后通过应用宝再唤起相应的 app,同时应用宝也开放了应用宝 App Link,可以做到唤起指定页面

    微信 API - launchApplication

    早期微信提供了launchApplicationgetInstallState方法来进行唤端。其中launchApplication可以直接唤起 App,getInstallState可以检查某个 App 是否安装(仅限安卓)。
    开通了白名单的应用,可以通过这两个 API 进行唤端。没开通的同学,现在应该很难开通了,可以使用微信推荐的开放标签来进行唤端

    这里简单梳理下launchApplication的使用流程

    1. 首先拿到签名进行 config 配置

    wx.config({debug: false,appId: conf.appId,timestamp: conf.timestamp,nonceStr: conf.noncestr,signature: conf.signature,beta: true,jsApiList: ['launchApplication', 'getInstallState'], // 使用这两个APIopenTagList: ['wx-open-launch-app'],
    })
    
    1. 使用如下两个 API 进行唤端操作

     /***  @description 微信拉起第三方App方法*  @param {Object} options -必填项,以json形式传参*  @param {String} options.appID - 必填项,供iOS使用*  @param {String} options.parameter - 必填项,schema://parameter 通过系统接口拉起第三方app。中文或特殊字符需要encode*  @param {String} options.extInfo - 必填项,该参数仅Android使用,对应Android微信opensdk中的extInfo,格式自定义,由第三方APP自行解析处理ShowMessageFromWX.Req 的微信回调* */launchApplication(options) {return WeixinJSBridge.invoke('launchApplication', options, res => {console.log(res)})}/***  @description 微信判断第三方App是否安卓 (仅仅Android支持, IOS无效、无法判断)*  @param {Object} options -必填项,以json形式传参*  @param {String} options.packageName - 必填项,安卓的包名*  @param {String} options.packageUrl - 必填项,schema 协议* */getInstallState(options) {return WeixinJSBridge.invoke('getInstallState', options, res => {console.log(res)})}
    

    经过上面的配置后,我们可以看一下微信端唤端的演示动图

    微信开放标签 - wx-open-launch-app

    微信开放标签是微信官方提供的唤端组件,具体使用方式可以参考官方文档[1]
    这里有个注意点,就是该功能需要一个公众平台的服务号和开放平台的账号以及应用进行绑定。因为我们公司的 App 绑定的公众平台与开放平台主体并不一样,所以这个功能没使用成功,有需求的同学可以试试

    开放平台与公众平台的区别,可以参考笔者过去的文章 (快速了解微信开放生态体系 - https://zhuanlan.zhihu.com/p/189968202)。

    自家 App 唤起其他 App

    最后要说下自家的 App 去唤起类似支付宝、微信等应用的情况。其实这个吧,对 FE 来讲也并不复杂,让 Native 人员提供一个方法给咱调用就行 ????。
    App 可以调用系统的 API,比如 openURL 等,可以很方便的唤起其它 App。这块对我们来说,需要注意的就是动态引入 App 的 sdk,保证唤起的时候 sdk 初始化完成。动态引入的具体逻辑,在源码中可以查阅到~

    源代码

    唤端的细节判断比较多,一篇文章很难说清楚,我们把转转使用的一个稳定版本的唤端库开源,方便大家交流学习,代码写的一般,主要供大家参考,同时也欢迎大家对代码进行吐槽,你们的吐槽是我们重构的源动力 ????
    源码地址:https://github.com/zhuanzhuanfe/call-app

    本月文章预告

    预告下,接下来我们会陆续发布转转在 Hybrid、微前端、Umi 等基础架构和中台技术相关的实践与思考,欢迎大家关注,期望与大家多多交流

    文末福利

    转发本文并留下评论,我们将抽取第 30 名留言者(依据公众号后台排序),送出《JavaScript 高级程序设计(第四版)》实体书一本,大家转发起来吧~

    Reference

    [1]

    官方文档: https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_H5_Launch_APP.html

唤起 App 在转转的实践相关推荐

  1. H5 唤起 APP的解决方案

    H5 唤起 APP的解决方案 参考文章: (1)H5 唤起 APP的解决方案 (2)https://www.cnblogs.com/yzhihao/p/8989195.html 备忘一下.

  2. 一切为了运营!如何从推广短信链接唤起 App?

    ●●● 需求描述 写这篇文章,也是缘于运营的一个需求:在 App 运营过程中,会有大量的推广短信,里面附有链接,目的是引导用户参与活动.如果用户手机没有安装我们的 App 就引导其去下载页,如果用户已 ...

  3. ArchSummit分享 | 高德地图App架构演化与实践

    讲师介绍 郝仁杰,高德地图无线开发专家.在7月13日落幕的2019年ArchSummit峰会上就高德地图近几年的App架构演化和实践进行了分享. 背景概述 高德是国内领先的数字地图内容.导航和位置服务 ...

  4. android app外唤起,Android 唤起app的多种方式

    方式一(通过Intent唤起): 我们自己的app代码: ComponentName componetName = new ComponentName( "com.lh.jimtrency. ...

  5. 解决微信环境下无法通过链接唤起App Store、微信访问App Store 链接白屏问题

    背景: 上周五临下班前,反馈群提出了个BUG(使用IOS在微信打不开App Store, 在浏览器下可以打开)并抛出了两个链接. 一个链接用于配置公众号的模板链接 http://xxxx.com/?p ...

  6. H5唤起APP进行分享的尝试

    H5唤起APP进行分享 最近很久没有写blog和note,倒是过家家的开发日志简单草草写了一点.这次记录下这个学习过程 由来 我们的 "通达有你",web h5页面的分享功能体验太 ...

  7. Android 桌面图标添加未读消息角标APP角标最佳实践

    Android 桌面图标添加未读消息角标APP角标最佳实践 本项目的完整演示代码 https://github.com/benchegnzhou/AndroidDevelomentArtDemo 最近 ...

  8. H5 如何实现唤起 APP

    前言 写过hybrid的同学,想必都会遇到这样的需求,如果用户安装了自己的APP,就打开APP或跳转到APP内某个页面,如果没安装则引导用户到对应页面或应用商店下载.这里就涉及到了H5与Native之 ...

  9. 一切为了营收!如何从推广短信链接唤起 App ?

    一.需求描述 写这篇文章,也是缘于运营的一个需求:在 App 运营过程中,会有大量的推广短信,里面附有链接,目的是引导用户参与活动.如果用户手机没有安装我们的 App 就引导其去下载页,如果用户已经安 ...

最新文章

  1. 浙江财经大学java试卷_2020年浙江财经大学社会保障考研真题试卷及试题答案,管理学考研试题下载...
  2. cad2014卡顿的解决方法_升级iOS14.1后出现卡顿、闪退?这3种方法可以解决
  3. 【IT资讯】MATLAB 不能用了,哪些替代品可以继续搞科研?
  4. 软件“美不美”,UI测试一下就知道
  5. 微课|中学生可以这样学Python(3.2节):双分支选择结构
  6. WinCE-多功能控件之无闪烁时间显示
  7. MarkDown数学符号(更新中)
  8. 推荐几款优秀的开源编程字体
  9. Mysql环境变量配置WIN10(保姆级)
  10. 读周公度之《结构化学基础》
  11. tensorflow聊天机器人python实现_用 TensorFlow 做个聊天机器人
  12. 转: 学习开源项目的若干建议(infoq)
  13. 三行代码搭建一个全能书籍系统(wiki)
  14. 领先大厂股价大跌,半导体行业形势不妙
  15. java开源论坛(轻量开源论坛)
  16. arch linux中的jdk的安装
  17. AJAX框架眼镜穿搭夏天,20套夏天穿搭!我帮你整理出来了
  18. 黑帽子Python——基础的网络编程工具——TCP的客户端和服务端
  19. 我的谷歌音乐播放器简介
  20. 基于DreamService的屏保

热门文章

  1. python如何缩放图片
  2. 简述常用人工神经网络方法的基本原理
  3. c语言编程师照片,C语言编程师工作简历范文
  4. 00.JavaScript基础
  5. 合并文件夹内所有Excel文件(目前仅限于合并单层文件夹,如果文件夹下面有文件夹,暂未加入此功能,默认合并所有文件的所有Sheet)优化文件名_变更为:文件夹名字 + 合并的文件-(xls+xlsx)
  6. js 常规打水印方法 canvas方法
  7. c语言课程设计fir滤波器设计,fir滤波器设计c语言
  8. 天猫网店转让新店可以转让吗
  9. 小米id锁状态查询_MySQL锁机制与事务隔离级别
  10. string转数组,数组转list