最近遇到的需求是:pc点击按钮,如果装了客户端,就打开客户端;如果没装客户端,跳转到pc下载客户端页面。
这个思路和之前h5打开app类似,不过比那个简单。
方案是:尝试打开客户端,设置定时器跳转下载页。若打开,则清除定时器。
直接上代码
// 调起客户端
export const launchCustomProtocol = (uri) => {
// 注册事件
function _registerEvent(target, eventType, cb) {
if (target.addEventListener) {
target.addEventListener(eventType, cb);
return {
remove: function () {
target.removeEventListener(eventType, cb);
}
};
} else {
target.attachEvent(eventType, cb);
return {
remove: function () {
target.detachEvent(eventType, cb);
}
};
}
}
// 插入隐藏的iframe
function _createHiddenIframe(target, uri) {
var iframe = document.createElement("iframe");
iframe.src = uri;
iframe.id = "hiddenIframe";
iframe.style.display = "none";
target.appendChild(iframe);
return iframe;
}
// 利用window的blur事件清除callback
function openUriWithHiddenFrame(uri, failCb) {
var timeout = setTimeout(function () {
failCb();
handler.remove();
}, 1000);
var iframe = document.querySelector("#hiddenIframe");
if (!iframe) {
iframe = _createHiddenIframe(document.body, "about:blank");
}
var handler = _registerEvent(window, "blur", onBlur);
function onBlur() {
clearTimeout(timeout);
handler.remove();
}
iframe.contentWindow.location.href = uri;
}
// 利用超时的hack方案清除callback
function openUriWithTimeoutHack(uri, failCb, successCb) {
var timeout = setTimeout(function () {
failCb();
handler.remove();
}, 1000);
//handle page running in an iframe (blur must be registered with top level window)
var target = window;
while (target != target.parent) {
target = target.parent;
}
var handler = _registerEvent(target, "blur", onBlur);
function onBlur() {
clearTimeout(timeout);
handler.remove();
successCb();
}
window.location = uri;
}
// firefox兼容
function openUriUsingFirefox(uri, failCb, successCb) {
var iframe = document.querySelector("#hiddenIframe");
if (!iframe) {
iframe = _createHiddenIframe(document.body, "about:blank");
}
try {
iframe.contentWindow.location.href = uri;
successCb();
} catch (e) {
if (e.name == "NS_ERROR_UNKNOWN_PROTOCOL") {
alert("Un Kown!")
failCb();
}
}
}
// 兼容ie,利用ie的MsLaunch
function openUriWithMsLaunchUri(uri, failCb, successCb) {
navigator.msLaunchUri(uri,
successCb,
failCb
);
}
// 判断浏览器类型
function checkBrowser() {
var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
return {
isOpera : isOpera,
isFirefox : typeof InstallTrigger !== 'undefined',
isSafari :/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent),
// isSafari : Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0,
isChrome : !!window.chrome && !isOpera
}
}
设置打开客户端失败的回调函数
function failCallback() {
window.location.href = location.origin + '/download'
}
let supported = true
if (navigator.msLaunchUri) { //for IE and Edge in Win 8 and Win 10
openUriWithMsLaunchUri(uri, failCallback);
} else {
var browser = checkBrowser();
console.log('browser', browser)
if (browser.isFirefox) {
openUriUsingFirefox(uri, failCallback);
} else if (browser.isChrome) { //
openUriWithTimeoutHack(uri, failCallback);
} else if (browser.isSafari) {
openUriWithHiddenFrame(uri, failCallback)
} else {
supported = false
return supported
}
}
}
测试该方案兼容以下浏览器:
Qq桌面浏览器
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6721.400 QQBrowser/10.2.2243.400
chrome
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36
360极速
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
360安全
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
safari
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.1 Safari/605.1.15
搜狗
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0
2345
Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; .NET4.0C; .NET4.0E; Tablet PC 2.0; rv:11.0) like Gecko
Copy
参考
Native-App-Protocal-Detection
How to detect browser's protocol handlers?
How to check if a custom protocol supported
custom-protocol-detection
AboutAsynchronousPluggableProtocols
网友评论