在网页中使用zxing条形码扫描器

12

有没有能够展示如何从网页中使用zxing条形码扫描器的工作示例?

参考此文档:https://github.com/zxing/zxing/wiki/Scanning-From-Web-Pages

下面的测试代码不应该可以工作吗?

function Test1()
{
 $.ajax(
 {
        url: "zxing://scan/?ret=http%3A%2F%2Ffoo.com%2Fproducts%2F%7BCODE%7D%2Fdescription&SCAN_FORMATS=UPC_A,EAN_13",
        success:function()
  {
            alert("success");
        },
        error:function()
  {
            alert("error");
        }
    });
}
 
function Test2()
{
 $.ajax(
 {
        url: "http://zxing.appspot.com/scan?ret=http%3A%2F%2Ffoo.com%2Fproducts%2F%7BCODE%7D%2Fdescription&SCAN_FORMATS=UPC_A,EAN_13",
        success:function()
  {
            alert("success");
        },
        error:function()
  {
            alert("error");
        }
    });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<button id="button1" onClick="Test1();">Test 1</button>
<br>
<br>
<button id="button2" onClick="Test2();">Test 2</button>

我在我的Android 4.4.2三星Galaxy TabPro和三星Galaxy S4上一直收到“错误”提示。

我已经尝试了原生浏览器、Chrome、Firefox和Dolphin浏览器。

甚至http://zxing.appspot.com/scan也无法正常工作,因为它总是要求我安装(已安装)的应用程序。

非常感谢任何帮助。

1个回答

22
ZXing不是为与AJAX一起使用而设计的。相反,它通过在默认浏览器中打开解析的URL来工作。从那时起,浏览器的行为主要负责用户体验。
有关此问题发布了几种方法; 不幸的是,并不存在适用于所有浏览器的单一方法。
某些浏览器,当您从命令行打开它们时,将检查URL是否已在另一个选项卡中打开,如果是,则使用该选项卡而不是新选项卡。如果zxing链接包含“zxing:// scan /?ret = mytab.html#{CODE}”,这将导致“onhashchange”事件。
其他浏览器不执行此类检查,因此我们会得到多个选项卡,所有这些选项卡都具有相同的URL(除哈希外),并且没有一个选项卡引发“hashchanged”事件。对于这些浏览器,我们需要尽可能重用缓存中的页面(以防止每次扫描时的网络流量),并更改localStorage值为哈希值。如果浏览器能够监听“存储”事件,我们可以使用它来触发代码。
下面的代码适用于Chrome,内在的Android浏览器和Firefox。它可能适用于其他浏览器,但我没有尝试过。但是,Firefox的一个警告是,如果将“dom.allow_scripts_to_close_windows”设置为“true”,扫描器窗口将仅关闭。
**此内容已编辑以更好地与允许扫描的多个页面配合使用,现在您可以使用不同的哈希而不干扰代码。**
**新版本12/19/16**
<!DOCTYPE html>
<HTML>
<HEAD>
<script type="text/javascript">

    if(window.location.hash.substr(1,2) == "zx"){
        var bc = window.location.hash.substr(3);
        localStorage["barcode"] = decodeURI(window.location.hash.substr(3))
        window.close();
        self.close();
        window.location.href = "about:blank";//In case self.close isn't allowed
    }
</script>
<SCRIPT type="text/javascript" >
    var changingHash = false;
    function onbarcode(event){
        switch(event.type){
            case "hashchange":{
                if(changingHash == true){
                    return;
                }
                var hash = window.location.hash;
                if(hash.substr(0,3) == "#zx"){
                    hash = window.location.hash.substr(3);
                    changingHash = true;
                    window.location.hash = event.oldURL.split("\#")[1] || ""
                    changingHash = false;
                    processBarcode(hash);
                }

                break;
            }
            case "storage":{
                window.focus();
                if(event.key == "barcode"){
                    window.removeEventListener("storage", onbarcode, false);
                    processBarcode(event.newValue);
                }
                break;
            }
            default:{
                console.log(event)
                break;
            }
        }
    }
    window.addEventListener("hashchange", onbarcode, false);

    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('window.removeEventListener("storage", onbarcode, false)', 15000);
        localStorage.removeItem("barcode");
        //window.open  (href + "#zx" + new Date().toString());

        if(navigator.userAgent.match(/Firefox/i)){
            //Used for Firefox. If Chrome uses this, it raises the "hashchanged" event only.
            window.location.href =  ("zxing://scan/?ret=" + encodeURIComponent(href + "#zx{CODE}"));
        }else{
            //Used for Chrome. If Firefox uses this, it leaves the scan window open.
            window.open   ("zxing://scan/?ret=" + encodeURIComponent(href + "#zx{CODE}"));
        }
    }

    function processBarcode(bc){
        document.getElementById("scans").innerHTML += "<div>" + bc + "</div>";
        //put your code in place of the line above.
    }

</SCRIPT>
<META name="viewport" content="width=device-width, initial-scale=1" />
</HEAD>
<BODY>
<INPUT id=barcode type=text >
<INPUT style="width:100px;height:100px" type=button value="Scan" onclick="getScan();">
<div id="scans"></div>
</BODY>
</HTML>

您可以创建一个JS包含文件来包含脚本的顶部块,并将其包含在需要扫描功能的所有页面上。
然后,在文档的正文中,您可以设置一个事件来调用 "getZxing()",它将调用您编写到页面中的"processBarcode(barcode)"。这里提供了一个简单的示例。
注意:第一次从您的页面运行zxing时,您将被要求选择默认应用程序。确保选择与您正在运行页面的浏览器相同的浏览器。此外,如果您之前选择了zxing的默认浏览器,并希望更改用于zxing的浏览器,则需要从其他浏览器中清除默认值。
非常感谢 @sean-owen 的辛勤工作和出色的产品。
更新12/19/16:
好的,我做了一个稍微更健壮的版本,适用于Firefox和Chrome。我发现了一些事情:
如果扫描仪未设置为自动打开Chrome,则Chrome将使用Storage事件,并且在成为默认设置后将使用Hash事件。
Firefox永远不会使用哈希事件,但除非使用window.location.href调用扫描仪,否则会打开额外的窗口(感谢@Roland)。
还有一些其他的异常情况,但没有破坏者。
我保留了哈希中的 "zx" 前缀,以便代码可以区分扫描器哈希和常规哈希。如果您将其保留在那里,则在processBarcode函数中将不会注意到它,并且非zx哈希将按预期操作。

@Mo-Prog,我终于加入了一个可工作的示例。对于10周的延迟我很抱歉!我还稍微调整了一下代码以防止多个监听器。 - alfadog67
使用存储事件是一个非常棒的想法,谢谢你分享这个技巧! :) - Pierre Maoui
作者@sean-owen可能想知道这个问题,但对我来说,这听起来像是浏览器的问题。你试过另一个浏览器吗?如果尝试了,请不要忘记重置默认操作... - alfadog67
感谢您提供这个优秀的代码。但我更喜欢您之前的解决方案:https://groups.google.com/d/msg/zxing/dQ4_wKjut1M/vOaguJIss3wJ 。在当前的解决方案中,我必须使用以下代码来删除zx前缀:processBarcode(unescape(hash).substr(2));。此外,浏览器的后退按钮不再起作用。扫描条形码后,每次单击后退按钮都会添加另一个相同条形码的副本。 - Roland
1
这太棒了。非常感谢。 - Abdul Rehman
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接