场景是:当我们做一些活动用来拉新等等时,通常会限制用户只在手Q中打开。比如用户通过微信扫码到了我们H5活动页面。那么我们就可以通过伪协议将手Q拉起,并且将H5页面打开。用户到达的途径有很多,比如通过浏览器,通过微信,通过其他APP应用。
正解代码
先不看原理的话,代码应该是像下面的。今天我也参照了许多别人的代码,但大多数不是这个不兼容,就是微信拉不起来。或者是 IOS 拉起正常,但是 Android 就是不行。这通常是由于代码没有完备造成的。更主要是因为我们的浏览器什么的都在时时更新。
1 | /** |
代码分析
正常情况下我们拉起手q,利用伪协议就可以了。伪协议是形如上面的不是http,https,ftp,之类的协议。例如:
1 | mqqapi://forward/url?src_type=internal&version=1&url_prefix='+ btoa(location.href) |
mqqapi是专门掉起手Q的, 后面的 btoa(location.href)是由于我们需要在手q打开我们的H5,所以这里要利用 location.href, 并且需要 base64的编码。这里的编码我们是利用的 window.btoa 函数。比起自己去编写 base64encode, 这个方法给我们提供了便利。
那么我们调用这一个 mqqapi 就可以了,为什么还要去判断一个 intent 呢?原因是:
Android 4.4 以上将原生的浏览器换成了chrome,而Android 5.开始的chrome不再允许传统的scheme拉起手q。 所以当打开的浏览器是 Android5 的时候,我们就要去调用这个 intent 新协议,而不是原来的 mqqapi协议。但是也要注意,这里的拉起app是需要用户操作的,需要用户确定(点击确认按钮)拉起才可以。所以不要用JS定时器了。
另外要注意 IOS 9.0 safari ,IOS 9.0以后,原生的safari不支持iframe 拉起 scheme 了。可以用 location.href/top.location.href拉起。
那么下面这些代码是什么呢?
1 | WeixinJSBridge.invoke("getInstallState", { |
WeixinJSBridge是微信浏览器内置的一个对象。JS API 建立在内置的这个对象中。但是有一个坑要注意。 WeixinJSBridge 不是我们一打开一个 WebView 就可以了的。我们需要在客户端初始化这个对象。当这个对象 ready 的时候,我们去监听,也就是这个 WeixinJSBridgeReady 事件。所以我们在调用这个 JS API 的时候,一定要判断下 WeixinJSBridge 是否存在。也就是
1 | typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function" |
这两句话的作用。
WeixinJSBridge.invoke
是 WeixinJSBridge 的一个方法,用来唤起相关的事件。这里我们唤起的是 getInstallState
这个事件。用来判断是否用户安装了 手机QQ。
当然还有很多别的 API,比如
1 | document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() { |
延伸和扩展
这里去学习了下下面这些的区别。是可能会碰到的坑。
- “top.location.href”是最外层的页面跳转
- “window.location.href”、”location.href”是本页面跳转 = self.location.href
- “parent.location.href”是上一层页面跳转.
其他方法
上面我们使用 window.open 打开的,其实我们还可以用 ifame 打开。如下面的代码:
1 | // ios 9 后,safari 打不开,可以用 location.href 或者 top.location.href 处理 |
主要这里也是一个简略的写法。可以更加完善的。