使用zxing实现HTML端适配iPhone及Android手机条码扫描器的问题咨询
问题根因定位
- iOS Safari对
window.open触发的自定义协议跳转有严格的拦截规则,只有用户主动点击瞬间触发的跳转才会被放行,你代码里的逻辑被判定为非用户直接触发行为后会被直接拦截,无任何报错提示 - iOS Safari在页面处于后台状态时,
storage事件会被冻结,扫描完成切回原页面后事件不会触发,导致无法拿到扫描结果 - iOS不允许未通过JS打开的页面调用
window.close(),你代码头部的页面关闭逻辑完全失效,无法完成结果回传 - 字符串形式的
setTimeout执行逻辑在iOS的内容安全策略下会被拦截,导致storage监听无法按时移除
修复方案
1. 调整自定义协议跳转逻辑
区分iOS设备,统一用window.location.href跳转,避免window.open被拦截:
function getScan(){ var href = window.location.href; var ptr = href.lastIndexOf("#"); if(ptr>0){ href = href.substr(0,ptr); } window.addEventListener("storage", onbarcode, false); // 替换字符串形式的setTimeout为函数形式 setTimeout(() => { window.removeEventListener("storage", onbarcode, false); }, 15000); localStorage.removeItem("barcode"); const ua = navigator.userAgent; if (ua.match(/iPhone|iPad|iPod/i) || ua.match(/Firefox/i)) { // iOS和火狐统一用location跳转,避免弹窗拦截 window.location.href = "zxing://scan/?ret=" + encodeURIComponent(href + "#zx{CODE}"); } else { window.open("zxing://scan/?ret=" + encodeURIComponent(href + "#zx{CODE}")); } }
2. 兼容iOS的结果监听逻辑
新增页面切回前台的主动校验,不单独依赖storage事件:
// 新增pageshow监听,切回页面时主动取localStorage的扫描结果 window.addEventListener('pageshow', () => { const bc = localStorage.getItem('barcode'); if (bc) { localStorage.removeItem('barcode'); processBarcode(bc); } });
3. 移除无效的页面关闭逻辑
修改头部的hash处理逻辑,删除iOS下不生效的window.close调用:
if(window.location.hash.substr(1,2) == "zx"){ var bc = decodeURI(window.location.hash.substr(3)); localStorage.setItem("barcode", bc); // 直接跳回原地址,无需尝试关闭页面 window.location.href = window.location.href.split('#')[0]; }
注意:iOS端微信、钉钉等App的内置浏览器禁止跳转第三方自定义协议,如果你的业务场景在这类App内运行,需要改用前端直接调用相机识别条码的方案,不要依赖ZXing客户端跳转。
内容的提问来源于stack exchange,提问作者심도현
相关产品推荐
相关产品推荐

