背景需求:

在H5网页中显示悬浮窗口,一般为主页顶部提示;若用户未装置 app 时,引导用户下载 app,若用户已装置app ,则引导用户翻开app ,完成网页与app 的无缝链接

调研

国外:

根据firebase: firebase.google.cn/docs

国内:

openinstall: www.openinstall.io

branch: cdn.branch.io/example.htm…

处理计划:

本文在项目中主讲根据firebase的deeplink技能唤醒App

作用展示

基于Firebase实现Deeplink 功能

Deeplink

背景:


从字面上理解为深度链接,拉新,促活,引流等手法,为进步用户活跃度促进用户的共享,需求支撑Deeplink相关功用。

计划:


根据Firebase的Deeplink:

首要流程图如下:

基于Firebase实现Deeplink 功能

其中需求特别阐明的是下载装置后翻开指定页面的功用,该功用现在能够有两个完成计划:

  1. App自己完成,首要经过剪切板完成,H5在跳转App Store之前将OpenUrl加密转存到剪切板,在用户装置完翻开App时扫描剪切板,扫描到则解析OpenUrl跳转指定页面,并清空剪切板内容

  2. 经过后台完成,H5跳转App Store之前将设备ID和OpenUrl上传后端,在装置完App翻开时调用接口查询OpenUrl(Firebase运用)

如下图所示:

基于Firebase实现Deeplink 功能

两个计划各有优势,剪切板方便集成,不依赖后端,相对简单,可是有一定局限性,必须用户装置完App后翻开App,不然或许呈现问题。

后端计划不受限于App何时翻开,只需后端保存有设备ID既能够随时翻开指定页面,一起能够记载链接点击次数的需求,可是开发难度较大,需前后端一起合作。

技能完成:

  1. index.html引进firebase
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/7.9.1/firebase-app.js"></script>
  1. app.js初始化firebase
//window.js文件
window.app.firebaseInfo = {  //firebaseConfig后管装备
    domainUriPrefix = ''
    firebaseConfig = {
      apiKey: '',
      authDomain: '',
      databaseURL: '',
      projectId: '',
      storageBucket: '',
      messagingSenderId: '',
      appId: ''
    }
}
// app.js文件 Initialize Firebase
const firebaseInfo = window.app.firebaseInfo
if (firebase) {
  firebase.initializeApp(firebaseInfo.firebaseConfig)
}
  1. 运用,点击翻开app按钮

# Firebase文档:

firebase.google.com/docs/refere…
firebase.google.cn/docs/dynami…

  1. 增加设备判别及生成短衔接
// 设备判别
  judgeDevice = () => {
    const ua = navigator.userAgent.toLowerCase()
    const isAndroid = ua.indexOf('android') > -1
    const isIOS = !!ua.match(/(i[^;]+;( u;)? cpu.+mac os x/) //判别是否是 iOS终端
    const isFacebookApp = ua.indexOf('fban') > -1 || ua.indexOf('fbav') > -1
    const isLineApp = ua.indexOf('line') > -1
    const isWeixin = ua.indexOf('micromessenger') > -1
    // 安卓设备,且在微信、facebook、line中翻开
    if (isAndroid && (isFacebookApp || isWeixin || isLineApp)) {
      // 增加蒙层引导
      const $body = document.getElementsByTagName('body')[0]
      //创立一个新元素插入原组件
      let divCover = document.createElement('div')
      divCover.innerHTML = `<p class="smart_app_text">點擊“\
      <span class=${
        isLineApp ? 'smart_app_text_line' : ''
      }>...</span>”選擇运用瀏覽器打開</p>\
      <img class="smart_app_img" src=${app.icons.ARROW} />`
      divCover.setAttribute('class', 'smart_app_cover')
      //插入到原父元素中
      $body.appendChild(divCover)
      // 封闭蒙层操作
      function closeMask() {
        let modalMask = document.getElementsByClassName('smart_app_cover')[0]
        modalMask.addEventListener('click', closeMask, false)
        $body.removeChild(modalMask)
      }
      divCover.addEventListener('click', closeMask, false)
    }
    this.openApp()
  }
  // 生成短衔接
  openApp = () => {
    const firebaseInfo = window.app.firebaseInfo
    const host = `https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=${
      firebaseInfo.firebaseConfig.apiKey
    }`
    // 针对活动列表特殊处理
    let link = window.location.href
    link =
      link.indexOf('/shop/productlist?activityId') > -1
        ? `${window.app.pathName}activityArea`
        : link
    let dynamicLinkInfo = {
      dynamicLinkInfo: {
        domainUriPrefix: firebaseInfo.domainUriPrefix,
        link: link,
        androidInfo: {
          androidPackageName: '' // Android 运用程序的包名称
        },
        iosInfo: {
          iosBundleId: '', // iOS 运用程序的绑缚包 ID
          iosAppStoreId: '' // 运用的AppStore ID,用于在未装置运用时将用户引导至AppStore
        },
        navigationInfo: {
          enableForcedRedirect: true
        }
      },
      suffix: {
        option: 'SHORT'
      }
    }
    if (window.app.getQueryString('utm_source')) {
      dynamicLinkInfo.dynamicLinkInfo.analyticsInfo = {
        googlePlayAnalytics: {
          utmSource: window.app.getQueryString('utm_source') || '',
          utmMedium: window.app.getQueryString('utm_medium') || '',
          utmCampaign: window.app.getQueryString('utm_campaign') || ''
        }
      }
    }
    window.app
      .posts('', JSON.stringify(dynamicLinkInfo), host, 'baseHeader')
      .then(res => {
        window.location.href = res.shortLink
      })
  }

唤端技能

唤端技能咱们也称之为deep link技能。当然,不同渠道的完成方法有些不同,一般常见的有这几种,分别是:

  • URL Scheme(通用
  • Universal Link (iOS)
  • App Link、Chrome Intents(android)

URL Scheme(通用)

这种方法是一种比较通用的技能,各渠道的兼容性也很好,它一般由协议名、路径、参数组成。这个一般是由Native开发的同学供给,咱们前端同学再拿到这个scheme之后,就能够用来翻开APP或APP内的某个页面了。

URL Scheme 组成

[scheme:][//authority][path][?query][#fragment]

常用APP的 URL Scheme

APP 微信 支付宝 淘宝 QQ 知乎
URL Scheme weixin:// alipay:// taobao:// mqq:// zhihu://

翻开方法

  • 直接经过window.location.href跳转
window.location.href = 'zhihu://'
  • 经过iframe跳转
const iframe = document.createElement('iframe')
iframe.style.display = 'none'
iframe.src = 'zhihu://'
document.body.appendChild(iframe)
  • 直接运用a标签进行跳转
  • 经过js bridge来翻开
window.miduBridge.call('openAppByRouter', {url: 'zhihu://'})

判别是否成功引发

Q: 当用户引发APP失利时,咱们期望能够引导用户去进行下载。那么问题是怎么才能知道当前APP是否成功引发?

A: 能够监听当前页面的visibilitychange事件,假如页面躲藏,则表示唤端成功,不然唤端失利,跳转到运用商铺。

完成

假如手机上并没有装置淘宝app,所以也就无法引发,此刻应该跳到运用商铺对应的运用下载页,完成如下:

<template>
  <div class="open_app">
      <div class="open_app_title">测验Demo</div>
      <div class="open_btn" @click="open">翻开淘宝</div>
  </div>
</template>
<script>
let timer
export default {
    name: 'openApp',
    methods: {
        watchVisibility() {
            window.addEventListener('visibilitychange', () => {
                // 监听页面visibility
                if(document.hidden) {
                    // 假如页面躲藏了,则表示引发成功,这时分需求铲除下载定时器
                    clearTimeout(timer)
                }
            })
        },
        open() {
            timer = setTimeout(() => {
              // 没找下载页,则跳转到store
                window.location.href = 'http://apps.apple.com/cn/app/id387682726'
            }, 3000)
            window.location.href = 'www.xxx.com://'
        }
    }
}
</script>
<style lang="less">
.open_app_title {
    font-size: (20/@rem);
}
.open_btn{
    margin-top:(20/@rem);
    padding:(10/@rem) 0;
    border-radius: (8/@rem);
    background: salmon;
    color: #fff;
    font-size: (16/@rem);
}
</style>

适用性

URL Scheme 这种方法兼容性好,不管安卓或许 iOS 都能支撑,是现在最常用的方法。

但它也有一些比较明显的缺点:

  • 无法精确判别是否引发成功,因为本质上这种方法便是翻开一个链接,而且还不是普通的 http 链接, 所以假如用户没有装置对应的 APP,那么尝试跳转后在浏览器中会没有任何反响,经过定时器来引导用户跳到运用商铺,但这个定时器的时刻又没有精确值,不同手机的唤端时刻也不同,咱们只能大概的估计一下它的时刻来完成,一般设为3000ms左右比较合适;

  • 从上面完成上能够看到会有一个弹窗提示你是否在对应 APP中翻开,这就或许会导致用户丢失;

  • 有 URL Scheme 绑架危险,比如有一个 app 也向体系注册了 taobao:// 这个 scheme ,引发流量或许就会被绑架到这个 app 里;

  • 简单被屏蔽,app 很轻松就能够拦截掉经过 URL Scheme 发起的跳转,比如微信内经常能看到一些被屏蔽的现象。

Universal Link (iOS)

Universal Link 是在iOS 9中新增的功用,运用它能够直接经过https协议的链接来翻开 APP。

它比较前一种URL Scheme的长处在于它是运用https协议,所以假如没有唤端成功,那么就会直接翻开这个网页,不再需求判别是否引发成功了。而且运用 Universal Link,不会再弹出是否翻开的弹出,对用户来说,唤端的效率更高了。

原理

  • 在 APP 中注册自己要支撑的域名;
  • 在自己域名的根目录下装备一个 apple-app-site-association 文件即可。

翻开方法

openByUniversal () {
  // 比如翻开知乎问题页
  window.location.href = 'https://oia.zhihu.com/questions/64966868'
},

适用性

  • 相对 URL Scheme,universal links 有一个较大长处是它唤端时没有弹窗提示是否翻开,提高用户体会,能够减少一部分用户丢失;

  • 无需关怀用户是否装置对应的APP,关于没有装置的用户,点击链接就会直接翻开对应的页面,因为它也是http协议的路径,这样也能一定程度处理 URL Scheme 无法精确判别唤端失利的问题;

  • 只能够在iOS上运用

  • 只能由用户主动触发

App Link、Chrome Intents(Android)

App Link

在2015年的Google I/O大会上,Android M宣告了一个新特性:App Links让用户在点击一个普通web链接的时分能够翻开指定APP的指定页面,条件是这个APP已经装置而且经过了验证,不然会显示一个翻开确认选项的弹出框,只支撑Android M以上体系。

App Links的最大的作用,便是能够防止从页面唤醒App时呈现的挑选浏览器选项框;

条件是必须注册相应的Scheme,就能够完成直接翻开相关的App。

  • App links在国内的支撑还不够,部分安卓浏览器并不支撑跳转至App,而是直接在浏览器上翻开对应页面。
  • 体系问询是否翻开对应App时,假如用户挑选“取消”而且选中了“记住此操作”,那么用户以后就无法再跳转App。

Chrome Intents

  • Chrome Intent 是 Android 设备上 Chrome 浏览器中 URI 计划的深层链接替代品。
  • 假如 APP 已装置,则经过装备的 URI SCHEME 翻开 APP。
  • 假如 APP 未装置,装备了 fallback url 的跳转 fallback url,没有装备的则跳转运用商场。

「 App Link、Chrome Intents;这两种计划在国内的运用都比较少。」

处理计划计划对比

Q&A URL Scheme Universal Link App Link
<ios9 支撑 不支撑 不支撑
>=ios9 支撑 支撑 不支撑
<android6 支撑 不支撑 不支撑
>=android6 支撑 不支撑 支撑
是否需求HTTPS 不需求 需求 需求
是否需求客户端 需求 需求 需求
无对应APP时的现象 报错/无反响 跳到对应的页面 跳到对应的页面

总结:

「URI Scheme:」

  • URI Scheme的兼容性是最高,但运用体会相对较差:

  • 当要被引发的APP没有装置时,链接报错,页面无反响。体会感差!

  • 当注册有多个scheme相同的时分,无法区分。

  • 不支撑从其他app中的UIWebView中跳转到方针APP, 所以ios和android都呈现了自己的独有处理计划。

「Universal Link」

  • 若用户已装置APP,则直接引发APP;反之则跳转到对应的web link。

  • universal Link 是从服务器上查询是哪个APP需求被翻开,所以不会存在冲突问题

  • universal Link 支撑从其他app中的UIWebView中跳转到方针app

  • 缺点:

此计划会记住用户的挑选:在用户点击了Universal link之后,iOS会去检测用户最近一次是挑选了直接翻开app仍是翻开网站。一旦用户点击了这个选项,他就会经过safiri翻开你的网站。而且在之后的操作中,默认一向延续这个挑选,除非用户从你的webpage上经过点击Smart App Banner上的OPEN按钮来翻开。

「App link」

  • 长处与 Universal Link 相似

  • 缺点在于国内的支撑相对较差,在有的浏览器或许手机ROM中并不能链接至APP,而是在浏览器中翻开了对应的链接。

  • 在问询是否用APP翻开对应的链接时,假如挑选了“取消”而且“记住挑选”被勾上,那么下次你再次想链接至APP时就不会有任何反响

以上调研及处理计划完成,假如对你有所参考和帮助,请加个重视、点个赞吧!感谢