h5唤起app

1,032 阅读2分钟

场景需求:我们经常会碰到这样一个需求,从app里面分享到微信的h5页面,用户打开后,页面上会有一个打开app的按钮,这个按钮实现的功能是:如果用户本地安装了该app,则打开app,并跳转到app中对应的页面;如果用户本地没有安装该app,则跳转到下载页。

注意:h5唤起app均在手机浏览器中才能实现,微信中无法唤起(微信做了限制,只有跟微信合作的才可以 ~摊手,无奈-.-),所以在微信中只能引导用户在浏览器中打开

一、h5唤起app的方式

  • 1、URL Scheme
  • 2、Universal Link(仅支持IOS9及以上)

二、URL Scheme

  • URL Scheme是App的一个特定的标识,是用来区分和定位app,通过这个URL Scheme我们可以取访问它,从而达到通信的目的。
  • 组成结构是:[scheme:][//[path][?query],如常见的URL Scheme有: 支付宝 alipay://,淘宝 taobao://等。(一般app端都有配置URL Scheme,直接找app端开发要)
  • path是跳转路径,可以跳到app指定路径,这个跟app端约定就行,app端获取这个参数进行跳转处理;query就是跳转时带的参数。这两个可以传也可以不传,就看怎么跟app端约定,如果是要跳到指定页面,一定是要传path的,不然就可能跳转app默认首页。
  • URL Scheme在IOS和安卓上都可以使用,直接使用window.location.href进行跳转就行。
  • 用法:
function jump2App(path, data) {
  // path 路径  data 传参对象
  const schemeUrl = 'xx://' // 你的URL Scheme
  let params = ''
  let locationUrl = `${schemeUrl}?path=${path}`
  // 拼接参数
  if (data && Object.keys(data).length > 0) {
    params = joinParam(data)
    locationUrl = `${schemeUrl}?path=${path}&${params}`
  }
  location.href = locationUrl
  
  // 跳转到下载页
  setTimeout(() => {
    location.href = '下载页链接'
  }, 300)
}
// 拼接参数
function joinParam(json) {
  if (!json) return ''
  return cleanArray(
    Object.keys(json).map(key => {
      if (json[key] === undefined) return ''
      return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
    })
  ).join('&')
}

// 在页面上调用
wakeUpHandle() {
  // 判断是否是微信环境,如果是微信环境,就提示用户打开浏览器
  if (this.isWX) {
    this.showBrowserTip = true
    return
  } else {
    jump2App('home', { id:123, name:'zs' })
  }
}
  • 但存在一个问题,因为h5一方面无法监测本地是否安装了app,另一方面也无法监测用户是否打开了app,所以只能通过延时器来判断。如果2秒内没有唤起app,则判断用户本地未安装app,则跳转到下载页(这是目前网上普遍使用的方法,说实话体验不是很好)。另外在IOS上,用户未安装app时,还看你出现safari无法打开,该网址无效的提示,并且这个问题无法解决!!!!坑爹啊 ~再次摊手,无奈-.- 我太难了。

三、Universal Link(通用链接)

本来想偷懒的,直接ios和安装都使用URL Scheme,但无奈ios那个提示网址无效没法解决,只能换种解决方案,就用Universal Link

  • Universal Link其实就是一个https的域名,如:https://aaa.bb.cn/,在该域名下有一个apple-app-site-association`文件,ios在项目工程中进行相应的配置(其实我也不知道是要配置啥,直接让ios配置好,把通用链接给你就行,哈哈)。
  • 这种方法仅IOS9及以上支持,IOS9之前的只能用URL Scheme。
  • Universal Link这种方法可以实现:用户本地安装app,直接唤起app;未安装app,就触发该域名下的重定向逻辑(很多文档这里没说怎么进行重定向,害我研究好久,可能自己比较菜吧)。其实重定向逻辑很简单,在这个域名下增加一个index.html,里面写一段jswindow.location.href = '下载页地址'就哦了。因为本司只兼容IOS9以上版本,所以这里就不做IOS9以前的兼容了。
  • IOS换上Universal Link直接体验好多了,不会出现网址无效的提示,也不用延时多少秒之后跳转。我还遇到一个坑就是传,啥参数都没有传可以唤起app,因为Universal Link是一个链接,我加了参数之后,未安装app,页面404,没有跳转到下载页,发现是因为加了参数之后是这样的https://aaa.bb.cn/?path=home&id=123&name=zs,这个链接并不是访问该域名下的index.html,好在我机智,用hash尝试了一下(因为我们项目就是hash模式),加了#之后可以访问index.html,https://aaa.bb.cn/#/path=home&id=123&name=zs,从而跳转下载页了。但是,IOS那边取参又有问题!!!!他需要#后面的那一块,然后就约定用一个特定的符号进行分割,就变成了这样https://aaa.bb.cn/#//path=home&id=123&name=zs,虽然不太好看,但总算实现了,一路艰辛。

以下是结合安卓和IOS最终的处理方法

// 区分安卓和IOS
function getUrl() {
  let appUrl = ''
  if (isAndroid()) {
  // Scheme 
    appUrl = process.env.VUE_APP_ANDROID_SCHEME
  }
  if (isIPhone() || isIPad()) {
  // Universal Link
    appUrl = process.env.VUE_APP_IOS_UNIVERSAL_LINK
  }
  return appUrl
}

export function jump2App(path, data) {
  // ios
  if (isIPhone() || isIPad()) {
    jump2IOSUrl(path, data)
    return
  }
  // android
  if (isAndroid()) {
    jump2AndroidUrl(path, data)
  }
  setTimeout(() => {
    location.href = '下载链接'
  }, 300)
}

export function jump2IOSUrl(path, data) {
  const appUrl = getUrl()
  let params = ''
  let locationUrl = `${appUrl}#//${path}`
  if (data && Object.keys(data).length > 0) {
    params = param(data)
    locationUrl = `${appUrl}#//${path}?${params}`
  }
  location.href = locationUrl
}

export function jump2AndroidUrl(path, data) {
  const appUrl = getUrl()
  let params = ''
  let locationUrl = `${appUrl}?path=${path}`
  if (data && Object.keys(data).length > 0) {
    params = joinParam(data)
    locationUrl = `${appUrl}?path=${path}&${params}`
  }
  location.href = locationUrl
}
// 拼接参数
function joinParam(json) {
  if (!json) return ''
  return cleanArray(
    Object.keys(json).map(key => {
      if (json[key] === undefined) return ''
      return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
    })
  ).join('&')
}

// 在页面上调用
wakeUpHandle() {
// 判断是否是微信环境,如果是微信环境,就提示用户打开浏览器
  if (this.isWX) {
    this.showBrowserTip = true
    return
  } else {
    jump2App('home', { id:123, name:'zs' })
  }
}

以上仅是个人遇到的问题,处理方式可能还存在问题,仅供参考,欢迎交流