Saturday, 15 March 2014

Reading Barcodes in Salesforce1

A little over a month ago I wrote a post on Reading QR Codes in Salesforce1. At the time I added an entry to my todo list to investigate barcode reading through a similar mechanism. A twitter post from @cherfeldman asking if this was possible in Salesforce1 moved it up to the top and so I started looking into it in earnest.

One of my key requirements was to be able to process the code on device, as I didn’t want to be sending high resolution images  from a phone or tablet back to the server, especially if I’m using what passes for mobile broadband outside of a big city in the UK.

Some goggling threw up a few JavaScript packages, but based on the demos provided by most of them, Eddie Larsson’s Barcode Reader looked to be the pick of the bunch. The demo page shows some pretty impressive decoding - multiple codes per image, blurry images, rotated through 90 + 180 degrees etc.  It also handles a number of formats - Code128, Code93, Code39 and EAN-13.

Creating a prototype in Visualforce was exceptionally straightforward - I just had to download the JavaScript that does the heavy lifting (DecoderWorker.js) and upload this as a static resource to my developer edition of Salesforce and then cut and paste the source of the example upload page and surround it with a few Visualforce tags. 

Screen Shot 2014 03 15 at 07 12 34

While it was great to get this working so easily, it wasn’t a huge amount of use as it stood, as it simply decodes the image and outputs the associated number. The first thing I did was to add a field to my account sobject of “Barcode”, so that scanning a barcode could take the user to a Salesforce record. I then tweaked the JavaScript to:

  • Output the time taken to decode 
  • Allow the user to choose when to decode the image, in case a picture didn’t turn out that great
  • Add a “Restart” button to reload the page, as hitting the back button and then trying to decode didn’t work 100% of the time
  • Execute a controller method via JavaScript remoting to retrieve the id of the matching record

Trying this out on my laptop decoded the barcode in around 3-4 seconds, however the same thing on my iPhone or iPad took some time and the user had no idea what was happening, so clearly something to hold their interest was required.

Looking at the underlying JavaScript, it makes use of HTML5 Web Workers to fire off multiple decoders to attack the barcode from various angles concurrently.  

var DecodeWorker = new Worker("{!URLFOR($Resource.DecodeWorker)}");
var RightWorker = new Worker("{!URLFOR($Resource.DecodeWorker)}");
var LeftWorker = new Worker("{!URLFOR($Resource.DecodeWorker)}");
var FlipWorker = new Worker("{!URLFOR($Resource.DecodeWorker)}");

where $Resource.DecodeWorker is the static resource reference for the DecodeWorker.js file.

Without web workers, things would be even slower as one decoder would have to finish before the next one could start, but I was still seeing decode times of around a minute.  I therefore decided to notify the user that the workers had been launched, and then post regular messages to indicate they were still running until they had either all completed or the barcode had been successfully processed.  I could do this through alerts or dialogs, but a few weeks ago Jeff Douglas’ Force.com Weekly linked to a rather nice JavaScript library for notifying users - alertify.js. I’ve used this a couple of times and its reliable, fast and looks great so I decided this was the way to go.

Adding alertify to a page is as simple as including three CSS and JavaScript files - I’ve uploaded the alertify zip as a static resource in my developer edition so I can include the files from that:

<apex:stylesheet value="{!URLFOR($Resource.alertify, 
'alertify.js-0.3.11/themes/alertify.core.css')}"/> <apex:stylesheet value="{!URLFOR($Resource.alertify,
'alertify.js-0.3.11/themes/alertify.default.css')}"/> <apex:includeScript value="{!URLFOR($Resource.alertify,
'alertify.js-0.3.11/lib/alertify.min.js')}"/>

I can then post a message to the user from JavaScript via a single function call:

alertify.log('Launching workers');

The user experience is now take a picture of a barcode or pick one from the device gallery, and click the “Decode” button if it looks good, as which point the user is told that work has started:

IMG 1153

while the workers are running, regular messages are alerted through a JavaScript timer:

interval=setInterval(function(){alertify.log('Still working');},5000);

 

IMG 1154

Then when the decoding completes, messages are displayed to indicate the success/failure and assuming success, the controller method is executed to find a record where the Barcode field matches the decoded value.

IMG 1157

the decoded value and time taken is then displayed, and a button to navigate to the record is displayed:

IMG 1158

Clicking the "Go to record” button goes to the record matching the barcode, which is my BrightGen account:

IMG 1159

The full page source is available at this gist, and the associated controller at this gist. You’ll also need to set up the static resources for:

  • alertify -  download the zip file, then upload as a static resource named ‘alertify'
  • decoder worker - download the file, then upload as a static resource named ‘DecodeWorker'.
    Note that this isn't coming from the github repository, as the code has changed since I originally wrote this post - instead this is the version that I downloaded back in 2014. 

Note that this won’t work on Android 4.4, as it appears that the ability to access the camera via a file input was removed from the chromium web view in this version - you can read more about this in the Cordova JIRA entry.

44 comments:

  1. Hi Bob Buzzard,

    Again great stuff from your side...
    This is really great.Bob I have created an Visualforce page tab and made it mobile enabled and taken the barcode snap whose Barcode number already exist in the Account record and tried up to decode but its doesn't show me up the 'Go to Record' button.Am I missing anything on my end,which is not allowing me to decode.

    Thanks,
    Atif.

    ReplyDelete
  2. Hey Tyler! Thanks for the info; just to follow up- did you ever have trouble with the barcodes you had to piece together? I did they work just fine out in the wild?
    Visite here

    ReplyDelete
  3. Thank you Bob, your posts helped me so much over the years! I tried this solution using the exact code samples from the gists and the js libraries you provided. The page works: image is loaded (desktop and mobile) and the alertify messages are running when I click "decode", but it never resolves to anything (no error messages, no results).. just keeps running (I tried over 20 min). The Decode Worker file is saved in the Static Resources as: MIME Type application/x-javascript. I was saving it as DecodeWorker.js file. Maybe that is the problem. Do you have any suggestions where I should look to find what exactly is not working? Thanks

    ReplyDelete
  4. I am getting the following error in the chrome developer tools console:
    Uncaught TypeError: Cannot read property 'length' of undefined

    from DecodeWorker.js

    ReplyDelete
  5. It seems the DecodeWorker.js has been modified:
    https://github.com/EddieLa/BarcodeReader/commit/e5cb3eac414804b63c22ca5dc311679878215749#diff-65cf2a514941677602e79d80b7a5bcb8

    Reversing these changes worked for me.

    ReplyDelete
  6. This comment has been removed by a blog administrator.

    ReplyDelete
  7. This comment has been removed by a blog administrator.

    ReplyDelete
  8. Very slow scanning on mobile device :(

    ReplyDelete
    Replies
    1. Yes, hence the details about it being slow in the post, and the recurring alerts to let the user know what is going on. Mobile devices just aren't as powerful as desktops.

      Delete
  9. It always says decoding failed so can you please help?

    ReplyDelete
  10. In the browser iIt worked really fast but in my iPhone it never ends. I added some try-catch just to verify it was not firing an error in the device and it is not.
    Any advice?

    Thanks

    ReplyDelete
  11. Does anyone know of a way to scan a QR code in Salesforce1 by actually using a mobile phone's scanner instead of taking a picture?


    Thanks

    ReplyDelete
  12. This comment has been removed by a blog administrator.

    ReplyDelete
  13. Thanks for your sharing,i learn a lot.Is there any standard/ acceptable way of generating barcodes in salesforce? I'm exporting some pdf reports and there I need to print a barcode. I found some third party libraries like this.
    But when we apply renderAs="pdf" is it still possible to do client side script calling?If not do I need to pre-generate the barcode for each and render it as jpg or similar? As it looks like this is kind of hot topic on success.SFDC.
    What is the optimum way for this.
    java barcode reader

    ReplyDelete
  14. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Anyone is having correct DecodeWorker.js file which is displaying barcode number as output?.

      Delete
    2. I've updated the link in the post to point to the version of the JavaScript that I used in my Salesforce dev org.

      Delete
  15. Hello Bob,

    Thanks for this useful content.

    I have installed the SF1 on my android device and currently using your code to knock out one of our requirement but looks like some issue with the Javascript code.

    On hitting decode, it just say "Still working" and never really proceeds further.
    Will you please help me out if i m missing out something here

    ReplyDelete
  16. This comment has been removed by a blog administrator.

    ReplyDelete
  17. This comment has been removed by a blog administrator.

    ReplyDelete
  18. This comment has been removed by a blog administrator.

    ReplyDelete
    Replies
    1. What is that got to do with this post? Could you please stop marketing/spamming such a wonderful post. Let people discuss the subject.

      Delete
  19. This comment has been removed by a blog administrator.

    ReplyDelete
  20. This comment has been removed by a blog administrator.

    ReplyDelete
  21. Hi Bob ,

    Thanks a lot for the useful content . It is working fine in my Android and ios device however as per the current code we can not decode all the types of Barcodes such as code 128 .

    Could you let us know if we can add all these types in our salesforce code so that we are able to decode all types of Barcode .

    thanks in advance !!!

    ReplyDelete
  22. Great blog Bob......Works awesome.....Bob rocks

    ReplyDelete
  23. Hi Bob,

    I have created an Visualforce page tab and made it mobile enabled and tried this in Android(v.4.2.2) in SF1 app but this does not allow me to open mobile camera. Although i uploaded static resources also. Am I missing anything on my end,which is not allowing me to open mobile camera.

    ReplyDelete
  24. This comment has been removed by a blog administrator.

    ReplyDelete
  25. I am reading your post from the beginning, it was so interesting to read & I feel thanks to you for posting such a good blog, keep updates regularly.

    ReplyDelete
  26. This is really informative. Thanks for sharing this article

    ReplyDelete
  27. Thanks for posting such a interesting blog and it is really informative. If you are interested in taking java as a professional carrier visit this website.JAVA Training in Chennai

    ReplyDelete
  28. Hi Bob,thanx for ur code, and i use the same code but i am gettting error like Resource is not found(Failed to load resource: the server responded with a status of 404 (Not Found)) can u help me to solve this error..please it's urgent to me..

    ReplyDelete
    Replies
    1. This usually means that one or more of the static resources is missing or incorrectly named. I suggest you post to the developer boards with your code snippets etc.

      Delete
  29. But that error is not related to the static resources it's related to the upload image..that to i am not able to preview the image.(for the image src i am getting this error..)Please help me

    ReplyDelete
    Replies
    1. The preview doesn't use a resource from the salesforce server - it places a data-uri directly in the page.

      Delete
    2. oh ok as of now it's working fine for all browsers except google chrome may i know reason for it..that preview also not available for google chrome

      Delete
  30. Hi BOB can help me for me why it's not working on chrome browserse help me

    ReplyDelete
  31. In Chrome for image i am getting following code

    "img height="240" id="picture" style="border:10px groove silver" width="320" src="blob:https%3A//XXXXXXXXXXX.visual.force.com/af3aef5f-c6f1-475d-90a5-2973ef5b6ae4"


    can u help me BOB please it's urgent for me

    thanks in advance...

    ReplyDelete
  32. Hi Bob,
    For me it's working fine in all browsers,but on salesfirce1 it always showing still working and unable to decode.Please give me some suggestions to workout barcode scanning..Thanks in advance..

    ReplyDelete
  33. Hello Bob,

    This post was really helpful to the Salesforce1 but in Salesforce1 it is always showing "Still Working", at the end it is showing as "Unable to decode". Are there any libraries which needs to be added for Salesforce1?

    If you could help me on this, that would be really great!!!

    ReplyDelete
  34. This is really informative. Thanks for sharing this article...

    ios training in chennai

    ReplyDelete
  35. Has anyone implemented this in Lightning?

    ReplyDelete