场景需求:我们经常会碰到这样一个需求,从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' })
}
}
以上仅是个人遇到的问题,处理方式可能还存在问题,仅供参考,欢迎交流