【问题标题】:Using zxing Barcode Scanner within a web page在网页中使用 zxing Barcode Scanner
【发布时间】:2014-12-09 00:00:00
【问题描述】:

是否有一个工作示例如何从网页使用 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 Samsung Galaxy TabPro 和 Samsung Galaxy S4 不断出现“错误”。 我尝试过常用的浏览器、Chrome、Firefox 和 Dolphin 浏览器。

即使http://zxing.appspot.com/scan 也不起作用,因为它总是要求我安装(已经安装的)应用程序。

任何帮助将不胜感激。

【问题讨论】:

    标签: javascript android web barcode zxing


    【解决方案1】:

    ZXing 不是为使用 AJAX 而设计的。相反,它通过在默认浏览器中打开已解析的 URL 来工作。从那时起,浏览器的行为主要负责用户体验。

    关于这个有几种方法;不幸的是,没有一种方法适用于所有浏览器。

    当您从命令行打开某些浏览器时,它们会检查该 URL 是否已在另一个选项卡中打开,如果是,将使用该选项卡而不是新选项卡。如果 zxing 链接包含“zxing://scan/?ret=mytab.html#{CODE}”,这将导致“onhashchange”事件。

    其他浏览器不执行此类检查,因此我们最终会得到多个选项卡,所有选项卡都具有相同的 URL(哈希除外),并且没有一个引发“hashchanged”事件。对于那些浏览器,我们需要尽可能重用缓存中的页面(以防止每次扫描时出现网络流量),并将 localStorage 值更改为哈希值。如果浏览器能够监听“storage”事件,我们可以使用它来触发代码。

    以下代码适用于 Chrome、内置 Android 浏览器和 Firefox。它可能适用于其他人,但我没有尝试过。不过,Firefox 的一个警告是,只有在 about:config 设置“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 的辛勤工作和出色的产品。

    2016 年 12 月 19 日更新

    好的,我做了一个更强大的版本,可以很好地与 Firefox 和 Chrome 配合使用。我发现了几件事:

    如果扫描仪未设置为自动打开 Chrome,Chrome 将使用 Storage 事件,并在成为默认设置后使用 Hash 事件。

    Firefox 永远不会使用 Hash 事件,但会打开一个额外的窗口,除非您使用 window.location.href 调用扫描仪(谢谢,@Roland)

    还有其他一些异常情况,但没有破坏交易。

    我在散列中留下了“zx”前缀,这样代码就可以在扫描散列和常规散列之间进行描述。如果将其留在其中,您将不会在 processBarcode 函数中注意到它,并且非 zx 哈希将按预期运行。

    【讨论】:

    • @Mo-Prog,我终于包含了一个工作示例。抱歉耽误了 10 周!我还稍微调整了代码以防止出现多个侦听器。
    • 使用存储事件是一个绝妙的主意,感谢您分享这个技巧! :)
    • 这是一篇令人难以置信的帖子。移动端数据有限的巨大解决方案。
    • 此编辑似乎对我不起作用。我正在进一步调查。谢谢阿尔法狗
    • 这太棒了。非常感谢
    猜你喜欢
    • 2014-10-30
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    • 2017-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多