如何检测浏览器或系统是否关联了geo:协议的导航程序?
检测系统是否关联geo:协议的可行方案
方案1:隐藏iframe加载+超时/失焦检测
通过创建隐藏iframe加载极简geo链接,结合超时和页面失焦事件判断是否存在关联程序:
function checkGeoProtocolSupport() { return new Promise((resolve) => { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = 'geo:0,0'; // 超时判断:1秒内无响应则认为无关联 const timeoutId = setTimeout(() => { document.body.removeChild(iframe); resolve(false); }, 1000); // 加载错误直接判定无关联 iframe.onerror = () => { clearTimeout(timeoutId); document.body.removeChild(iframe); resolve(false); }; // 页面失焦说明唤起了外部程序,判定有关联 const handleBlur = () => { clearTimeout(timeoutId); document.body.removeChild(iframe); window.removeEventListener('blur', handleBlur); resolve(true); }; window.addEventListener('blur', handleBlur); document.body.appendChild(iframe); }); } // 实际应用 checkGeoProtocolSupport().then(hasSupport => { const geoLink = document.querySelector('a[href^="geo:"]'); if (hasSupport) { // 保留原geo协议链接 geoLink.href = geoLink.getAttribute('href'); } else { // 替换为OpenStreetMap导航链接 const coords = geoLink.href.replace('geo:', ''); geoLink.href = `https://www.openstreetmap.org/directions?to=${coords}`; } });
注意:部分浏览器会拦截iframe加载geo协议,此时会触发onerror返回false;页面失焦判断可能存在误判(比如用户主动切换窗口),可根据实际场景调整超时时间。
方案2:window.open+窗口状态检测
通过window.open打开geo链接,根据窗口是否自动关闭判断是否存在关联程序:
function checkGeoProtocolSupport() { return new Promise((resolve) => { const testWin = window.open('geo:0,0'); if (!testWin) { // 弹窗被拦截,默认按无关联处理 resolve(false); return; } const timeoutId = setTimeout(() => { if (testWin.closed) { resolve(true); } else { testWin.close(); resolve(false); } }, 1000); // 窗口关闭时直接判定有关联 testWin.addEventListener('beforeunload', () => { clearTimeout(timeoutId); resolve(true); }); }); }
注意:该方法会触发浏览器弹窗拦截提示,需要用户允许弹窗;部分浏览器唤起程序后不会自动关闭测试窗口,可适当延长超时时间。
方案3:混合策略(推荐)
先通过用户代理区分移动端和桌面端:
- 移动端直接保留geo协议链接(绝大多数移动设备都有地图应用支持geo协议)
- 桌面端再用上述检测方法,根据结果决定保留原链接还是替换为OpenStreetMap链接
这种方式既能减少桌面端不必要的检测操作,又能兼顾移动端的兼容性。
内容的提问来源于stack exchange,提问作者user9011377
相关产品推荐
相关产品推荐

