Adding a QR Code Reader in Flex on Android

Posted on Jun 22, 2011

One of the features I commonly see requested for Android applications is QR code reader or barcode scanner integration. Some native Android applications actually use an external application for QR code/barcode scanning. That, as far as I know, is not an option at the moment in AIR on Android. However, thanks to the open source ZXing library, some direction from Amer Dababneh and a blog post by Michael B, I was able to create basic sample Flex-based mobile application that accessed the camera and read QR codes. This blog post will show you how.

For any smart asses out there (yes, I mean you Ray) - yes, I can still code. It’s just been a while since I had something “blogworthy.” :)

Create Your Project
To begin with, of course, you need to create your new Flex mobile project - I used a standard view-based application. I should note that while I only tested this on Android (via my Nexus One), it’s entirely possible that this code will work as is on iOS or Blackberry Tablet OS via the recent Flash Builder 4.5.1 update.

The important thing to note here is that you will need to enable Camera permissions in your app.xml file. This can be done during the new project wizard or by manually adding the below items to your app.xml within the Android “manifestAdditions” section:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.autofocus"/>

In my experience, if you forget to do this or don’t do it properly, the camera will simply fail silently (which can lead to needless debugging frustration - so just don’t forget).

Adding the Camera
Now that we’ve created our new Flex mobile application, we need to lay out our sample application. My sample is very simple with only a home view that contains the camera, a label to display any results and a button to start the process and capture the QR codes. For reference, I borrowed some of the camera placement code from this blog post by Guillaume.

You can see the visual elements of the page laid out below. The SpriteVisualElement is the container that will hold the view to our camera.

<s:VGroup width="100%" horizontalAlign="center" id="vg">
   <s:SpriteVisualElement id="sv" width="360" height="400"/>
   <s:Label id="lbl" text="" />
   <s:Button id="btn" label="Start Camera" width="220" height="93" click="button1_clickHandler(event)"/>
</s:VGroup>

The first time the user clicks the button, it will start the camera. Inside my click handler for the button, I have the following code that first gets an instance of the Camera, attaches it to a VideoDisplay object which is added as a child to our SpriteVisualElement. We also initialize our QRCodeReader class which is from the ZXing library.

if (Camera.isSupported)
{
   camera=Camera.getCamera();
   camera.setMode(360, 360, 24);
                  
   videoDisplay.x = 360;
   sv.addChild(videoDisplay);
   
   videoDisplay.attachCamera(camera);
   videoDisplay.rotation=90;
   qrReader=new QRCodeReader;
   btn.label = "Scan Now";
   lbl.text = "";
   cameraStarted = true;
}
else {
   lbl.text = "no camera found";
}

If you ran your app right now (see the full code at the end of this post for all the necessary variables and imports) you would see a view into your device’s camera appear once you click the button to start - that is if our QRCodeReader wasn’t throwing compile errors. Let’s get those fixed.

Modifying the ZXing Library
Obviously, in order to create this project you must download the ZXing library from Google Code. Simply dump the library into your “src” folder where it should be under a com.google.zxing package. As I noted, you will get some complile errors as soon as you try to use the necessary files for QRCodeScanning. Luckily they are very easy to correct as they all involve unnecessary or missing imports.

Here are the changes required to get this working on our project:

  • In QRCodeMultiReader add import com.google.zxing.BinaryBitmap; (or just press ctrl+space after the BinaryBitmap on the line with the compile error and have Flash Builder add the import for you);
  • In DecoderResult comment out import of mx.controls.List;
  • In BufferedImageLuminanceSource comment out import mx.controls.Image;.

Reading the QR Code
Most of the ZXing library usage code to read the QR code was taken verbatim from the blog post by Michael B referenced above. The decodeSnapshot method, which is triggered when the user presses the button to capture a QR code, gets the bitmap data from the Camera and passes it to the decodeBitmapData method. The decodeBitmapData method mostly handles passing this bitmap data to the ZXing library for decoding and then displaying the result in the label. The getAllHints method actually tells the ZXing library what kind of QR/barcode we are trying to decode. Theoretically, if you wanted to decode other standard barcode types, you would just add those to the hashtable. ZXing supports many types of barcode scanning and if you simply add the other types, it should just work - but I emphasize should because I didn’t test it yet.

public function decodeSnapshot():void
{
   lbl.text="checking...";
   bmd=new BitmapData(300, 300);
   bmd.draw(videoDisplay, null, null, null, null, true);
   videoDisplay.cacheAsBitmap=true;
   videoDisplay.cacheAsBitmapMatrix=new Matrix;
   decodeBitmapData(bmd, 300, 300);
   bmd.dispose();
   bmd=null;
   System.gc();
}
         
public function decodeBitmapData(bmpd:BitmapData, width:int, height:int):void
{
   var lsource:BufferedImageLuminanceSource=new BufferedImageLuminanceSource(bmpd);
   var bitmap:BinaryBitmap=new BinaryBitmap(new GlobalHistogramBinarizer(lsource));

   var ht:HashTable=null;
   ht=this.getAllHints();
            
   var res:Result=null;
   try {
      res=qrReader.decode(bitmap, ht);
   }
   catch (event:Error) {
   }
            
   if (res == null) {
      videoDisplay.clear();
      lbl.text="nothing decoded";
   }
   else {
      var parsedResult:ParsedResult=ResultParser.parseResult(res);
      lbl.text=parsedResult.getDisplayResult();
      sv.removeChild(videoDisplay);
      cameraStarted = false;
      btn.label = "Start Camera";
   }
}
         
public function getAllHints():HashTable
{
   var ht:HashTable=new HashTable;
   ht.Add(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
   return ht;
}

Testing Your QR Code Reading
For testing, I used this QR Code generator for encode both URL and straight text encoded QR codes. In my tests, not only did the QR code reading work well but it ran pretty fast (and my Nexus One is no powerhouse any longer - if it ever was). One thing I did note though is that it can be pretty picky about where the QR code is placed within the image. It should be centered and should not be so close that it takes up the entire camera. I think this is partly because we are actually passing only a 300x300 bitmap out of our 360x360 camera image to be decoded, so this might be fixable. If that isn’t correctable in that manner than I thought it would be wise to add some guides as an overlay to help the user know where to align the QR code.

The other thing I noticed was that when I created a timer event and tested checked the camera periodically using that (as in the linked sample I sourced), I did get some performance issues where the app periodically became unusable (mostly during debugging mode but it seemed indicative of a problem you’d want to potentially eliminate).

That’s it. Not too complicated eh? For reference, below is the finished Flex Mobile View with all the elements you need to get this sample running. Let me know if this helps you or if you manage to expand upon the example (and feel free to share your code if you do).

P.S. I am not posting an FXP because I am unsure if there are any redistribution restrictions on the license for ZXing.

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx"
      xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">

   <fx:Declarations>
      <!-- Place non-visual elements (e.g., services, value objects) here -->
   </fx:Declarations>
   <fx:Script>
      <![CDATA[
         import com.google.zxing.BarcodeFormat;
         import com.google.zxing.BinaryBitmap;
         import com.google.zxing.BufferedImageLuminanceSource;
         import com.google.zxing.DecodeHintType;
         import com.google.zxing.Result;
         import com.google.zxing.client.result.ParsedResult;
         import com.google.zxing.client.result.ResultParser;
         import com.google.zxing.common.BitMatrix;
         import com.google.zxing.common.ByteMatrix;
         import com.google.zxing.common.GlobalHistogramBinarizer;
         import com.google.zxing.common.flexdatatypes.HashTable;
         import com.google.zxing.qrcode.QRCodeReader;
         import com.google.zxing.qrcode.detector.Detector;
         
         import spark.events.ViewNavigatorEvent;
         
         protected var camera:Camera;
         private var videoDisplay:Video=new Video(360, 360);
         private var qrReader:QRCodeReader;
         private var bmd:BitmapData;
         private var cameraStarted:Boolean = false;
         
         protected function button1_clickHandler(event:MouseEvent):void
         {
            if (!cameraStarted) {
               if (Camera.isSupported)
               {
                  camera=Camera.getCamera();
                  camera.setMode(360, 360, 24);
                  
                  videoDisplay.x = 360;
                  sv.addChild(videoDisplay);
                  
                  videoDisplay.attachCamera(camera);
                  videoDisplay.rotation=90;
                  qrReader=new QRCodeReader;
                  btn.label = "Scan Now";
                  lbl.text = "";
                  cameraStarted = true;
               }
               else {
                  lbl.text = "no camera found";
               }
            }
            else {
               decodeSnapshot();
            }
         }
         
         public function decodeSnapshot():void
         {
            lbl.text="checking...";
            bmd=new BitmapData(300, 300);
            bmd.draw(videoDisplay, null, null, null, null, true);
            videoDisplay.cacheAsBitmap=true;
            videoDisplay.cacheAsBitmapMatrix=new Matrix;
            decodeBitmapData(bmd, 300, 300);
            bmd.dispose();
            bmd=null;
            System.gc();
         }
         
         public function decodeBitmapData(bmpd:BitmapData, width:int, height:int):void
         {
            var lsource:BufferedImageLuminanceSource=new BufferedImageLuminanceSource(bmpd);
            var bitmap:BinaryBitmap=new BinaryBitmap(new GlobalHistogramBinarizer(lsource));
            
            var ht:HashTable=null;
            ht=this.getAllHints();
            
            var res:Result=null;
            try {
               res=qrReader.decode(bitmap, ht);
            }
            catch (event:Error) {
            }
            
            if (res == null) {
               videoDisplay.clear();
               lbl.text="nothing decoded";
            }
            else {
               var parsedResult:ParsedResult=ResultParser.parseResult(res);
               lbl.text=parsedResult.getDisplayResult();
               sv.removeChild(videoDisplay);
               cameraStarted = false;
               btn.label = "Start Camera";
            }
         }
         
         public function getAllHints():HashTable
         {
            var ht:HashTable=new HashTable;
            ht.Add(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
            return ht;
         }
         
      ]]>
   </fx:Script>
   <s:VGroup width="100%" horizontalAlign="center" id="vg">
      <s:SpriteVisualElement id="sv" width="360" height="400"/>
      <s:Label id="lbl" text="" />
      <s:Button id="btn" label="Start Camera" width="220" height="93" click="button1_clickHandler(event)"/>
   </s:VGroup>
</s:View>

Comments

Kapteijn-Design Thnx for the example and code... i gonna try it, because my example didn't work

Posted By Kapteijn-Design / Posted on 06/22/2011 at 7:14 AM


cyndev Great post and works well. One issue that is coming up is the camera freezes when the device changes orientation. Tried a couple of ways to listen for stage orientation change and reset camera, no luck. Any suggestions would be helpful. If I solve it I will post it here.

Posted By cyndev / Posted on 06/26/2011 at 4:55 PM


Brian Rinaldi @cyndev While researching this post I found one that showed camera rotation. I did not test it however, so let me know if it works. http://riasandbox.com/?p=32

Posted By Brian Rinaldi / Posted on 06/27/2011 at 6:00 AM


cyndev Thx for the link. The problem revolves around the actual camera keeping the same orientation as the device changes orientation. It is outside your code but and interesting situation especially for tablets.

Posted By cyndev / Posted on 06/27/2011 at 11:13 AM


Monika Thanks for a great example.But while creating a Flex Mobile project in Flash Builder 4.5.1, I am not able to dump the zxing src folder in the source folder of the project because it says, "the source folder is not a Java project". Morover even if i copy paste the files,the Flash Builder doesnt import or suggest.
How can I import the zxing files? Can i create an .swc out of it?

Thanks
Monika

Posted By Monika / Posted on 06/29/2011 at 7:05 AM


Brian Rinaldi @Monika - all I did was download the library and copy/paste the folder into /src within my mobile project. There is no need to do an import or to do anything during the project creation.

Posted By Brian Rinaldi / Posted on 06/29/2011 at 7:08 AM


cyndev @Monika all I did was drag and drop the com folder to src in my project and it worked. Appears you are pulling the Java src (zxing-1.6/core) versus pulling over the actionscript/core/src/com just drop the com folder in and make the adjustment Brian mentioned and it should work. Hope this helps.

Posted By cyndev / Posted on 06/29/2011 at 7:18 AM


Monika Hi Brian,
The problem is the library gets downloaded as a 65 MB zip file. The needed Java files are in the "zxing/core/src" folder of the zip when extracted. I am copy pasting this src folder into the project source folder but the imports in the HomeView page of the project show errors.

I think we can access Java files in a flex project only through remote objects and not directly. Please let me know if I am doing some mistake.

Thanks
Monika

Posted By Monika / Posted on 06/29/2011 at 7:21 AM


Monika @cyndev Oh yes. I understood the mistake I was doing. I was dragging the core/src folder instead of the actionscript/core/src.Its shows no errors now. Thanks a lot for your help.
@brian Thanks a lot :)

Posted By Monika / Posted on 06/29/2011 at 7:26 AM


Brian Rinaldi @Monika @cyndev please note that the version I testing was ZXing 1.6 (though a newer version has since been released) and the source you want is in /zxing-1.6/actionscript once you unzip.

I don't know if any changes were made to the AS version in 1.7 but if anyone tests the 1.7 release, please let me know if they affect the above instructions.

Posted By Brian Rinaldi / Posted on 06/29/2011 at 7:30 AM


Monika I am trying it with ZXing 1.7. Will comment if it needs any changes to work with your example.

Thanks

Posted By Monika / Posted on 06/29/2011 at 7:44 AM


Michael Ahmed I loaded up 1.7 into my current project, made the adjustments. It is working like 1.6. Tested decoding and works fine.

Posted By Michael Ahmed / Posted on 06/29/2011 at 8:09 AM


Monika I deployed the app on Samsung galaxy tab but my camera is not starting. I have included the settings in the app.xml within the Android “manifestAdditions” section also but its not working and finally I get "nothing decoded". :(

What could possibly be going wrong?

Posted By Monika / Posted on 06/30/2011 at 2:09 AM


Monika Find out the mistake. Thanks:) The example works great with ZXing 1.7 too. Just need to take care while capturing the image.

Posted By Monika / Posted on 06/30/2011 at 3:02 AM


Monika Works fine on iOS. Just tested on iPhone. :) Just that takes little long time to scan the qr code depending on how well the image has been captured.

Posted By Monika / Posted on 06/30/2011 at 3:44 AM


Brian Rinaldi @monika - yes, as I explain in the post it is very particular about the location of the qr code within the camera. Thus, this is why I suggest if this a production app, I would add some kind of guide image over the camera to help the user properly center the qr code. Glad to hear it works on iOS.

Posted By Brian Rinaldi / Posted on 06/30/2011 at 4:38 AM


Venkat Williams I tried this application using HTC Desire but camera not able to scan the QR code. Getting nothing decoded exception. What could be the problem.

Posted By Venkat Williams / Posted on 07/04/2011 at 4:54 AM


Brian Rinaldi @Venkatesh "Nothing is decoded" just means its not properly seeing your QR code. As noted in the post and comments, it needs to be centered but not too close. Try it again at different distances and you'll probably get it.

Posted By Brian Rinaldi / Posted on 07/05/2011 at 6:32 PM


Monika Hi,
Is it possible to zoom the camera from a distance while capturing the qr coded image?

Thanks

Posted By Monika / Posted on 07/06/2011 at 1:05 AM


Brian Rinaldi @Monika - I am not certain but I don't believe that is possible just yet. Maybe with native extensions down the road.

Posted By Brian Rinaldi / Posted on 07/06/2011 at 5:17 PM


Monika @brian I tried to use the native camera on Samsung Galaxy through CameraUI class and integrated with the above code for QR code reading. But somehow it shows "nothing decoded" in all cases. Just not able to figure out where am i going wrong.A sample of my code is as below:
private function onMediaPromiseLoaded(e:Event):void{
var mpLoaderInfo:LoaderInfo = e.target as LoaderInfo;
            mpLoaderInfo.removeEventListener(Event.COMPLETE, onMediaPromiseLoaded);
            mpLoaderInfo.loader.removeEventListener(IOErrorEvent.IO_ERROR, onMediaPromiseLoadError);

bmd=new BitmapData(400, 400);
            bmd.draw(mpLoaderInfo.loader.content, null, null, null, null, true);
            decodeBitmapData(bmd, 400, 400);
bmd.dispose();
bmd=null;
System.gc();   }

decodeBitmapData is the same function given above.

Posted By Monika / Posted on 07/06/2011 at 11:10 PM


Venkat Williams While I am trying to run this example in Mobile device    videoDisplay.attachCamera(camera); not working.

Anyone of tried to scan a QR Code using mobile device.

Please help me which component I need to use to attach to the VideoDisplay.

-Venkat

Posted By Venkat Williams / Posted on 07/11/2011 at 4:55 AM


Monika @venkat It works fine for me. What is the error being shown and where?

Posted By Monika / Posted on 07/11/2011 at 5:26 AM


Brian Rinaldi @Venkat - be sure you modified the app.xml, that is usually where the problem lies.

@Monika - the CameraUI isn't really that useful I would think for this purpose as it would require they keep leaving to the native camera app and returning to see if it was properly positioned for decoding - seems tedious and unfriendly. Plus, I would think you might have issues being that the native camera returns much larger images.

Posted By Brian Rinaldi / Posted on 08/03/2011 at 12:34 PM


mc I made the changes to the ZXing library. But I'm still getting errors... such as "-1046: Type was not found or was not a compile-time constant: HashTable."

Any suggestions?

I downloaded the latest version of ZXing.

Posted By mc / Posted on 08/21/2011 at 7:21 PM


Brian Rinaldi @mc perhaps they updated the code. I typically just ran through the code and searched for these sorts of issues and resolved them either by importing or commenting out the import. If I have the chance I will look into this and report back.

Posted By Brian Rinaldi / Posted on 08/22/2011 at 8:02 AM


mc @brian Thanks! Do you remember which version you used in your implementation? Maybe I can grab an old version.

My experience with flex is limited, so I did not know exactly what to look for. And as you have probably experienced... the error messages were not as helpful as I'd like.

Posted By mc / Posted on 08/22/2011 at 8:15 AM


Brian Rinaldi @mc - a number of people on the comments have mentioned using 1.7, which is the current release, and getting it to work. However I think I used 1.6.

Posted By Brian Rinaldi / Posted on 08/22/2011 at 10:04 AM


Charles "1046: Type was not found or was not a compile-time constant: HashTable"
The same error appears when i am trying to compile, have been searching for the whole afternoon but not able to find a solution.

Posted By Charles / Posted on 08/24/2011 at 2:44 AM


Monika @charles Just remove the import for Hashtable. I guess Hashtable is not being used anywhere.

Posted By Monika / Posted on 08/24/2011 at 3:53 AM


Monika @charles One of the places where HashTable is imported is like this import com.google.zxing.common.flexdatatypes.HashTable; in EmailAddressResultParser.as. Just check if the HashTable class is present in the required location.

Posted By Monika / Posted on 08/24/2011 at 4:34 AM


mc @charles I had the same issue. When you put zxing into your SRC folder. Copy over the com folder.

I had core/com...etc.. in there and I had that error.

It should be src/com

Posted By mc / Posted on 08/24/2011 at 5:54 AM


Charles @mc thanks a lot, that solves the problem.
@Monika, thanks for the suggestion, I was putting the whole zxing folder under /src folder. only put core/com under /src solve the problem.

Posted By Charles / Posted on 08/25/2011 at 12:45 AM


Miguel IM using this on flash.
I did import etc.. the only error right now is:
...\ResultParser.as, Line 261   1120: Access of undefined property StringUtil.

and

\ResultParser.as, Line 25   1172: Definition mx.utils:StringUtil could not be found.


What i do now?

Posted By Miguel / Posted on 08/29/2011 at 1:26 PM


Rahul Joshi Hi,

Thanks for the great post. I have created a QR code reader which continuously senses for any QR code and shows the info below.
I have followed the blog post by Michael B also.
I tried application in my Xperia X10 and the performance is good but when my friend tried it on his Galaxy S, which has same processor as X10 but more RAM, the performance wasn't that good.
Any idea how it could be optimized?

Posted By Rahul Joshi / Posted on 09/04/2011 at 9:27 PM


Brian Rinaldi @rahul - I am surprised that the Galaxy S has an issue. I assume the problem was in the decoding of the QR code and, since I didn't write that code (nor do I have a Galaxy S for testin), I don't really have any insight into the bottlenecks.

Posted By Brian Rinaldi / Posted on 09/06/2011 at 6:01 AM


Charles Hi,
Me again :)thanks for all the help.

I have build an iphone qr-code reader with the code and it runs well with the rear camera, but when using the front camera everything goes fine but the decode never success.
Wat could be the problem there?

Posted By Charles / Posted on 09/07/2011 at 1:15 AM


Vivek I have pasted the same code and did the changes also and past full zxing file also but still getting error in this function

* public function getAllHints():HashTable

Can anyone help me..

Posted By Vivek / Posted on 09/12/2011 at 10:26 PM


Brian Rinaldi @Charles - not sure why that would be, sorry.

@Vivek - what is the error?

Posted By Brian Rinaldi / Posted on 09/13/2011 at 4:42 AM


Vivek Thanx @Charles for consider my error is

"type was not found or was not a compile-time constant:Hasttable"

Posted By Vivek / Posted on 09/15/2011 at 10:59 PM


Laura Thanks for all these information ?

Is it possible to write a QrCode besides reading it ?
Thank ;)

Posted By Laura / Posted on 09/30/2011 at 1:20 PM


Rahul Joshi @Laura, yes definitely. You can do that using the same Zxing library. Check this link: http://riarockstars.com/2011/03/11/creating-qr-codes-in-actionscript/

Posted By Rahul Joshi / Posted on 09/30/2011 at 11:59 PM


mc Anyone having trouble with this on Android 2.3.4? I'm testing on a verizon bionic. Once the camera is activated... all I'm seeing is redish static/blocks being displayed.

Posted By mc / Posted on 10/10/2011 at 2:13 PM


chnauman I wrote a piece of code for getting raw camera, not UICamera. I allowed camera from app.xml for android.
Now the app is working perfect on android, but it is not fetching camera for iOS. I am trying it on iPhone 4g.
anyone can help.. ? thanks in advance..

Posted By chnauman / Posted on 10/13/2011 at 12:53 AM


mc @chnauman. Does getting raw camera work using Android 2.3.4? If so, would you mind sharing your work around?

Posted By mc / Posted on 11/02/2011 at 6:34 AM


Warren What modifications would I make to get this code to work with a barcode like code128 (or other)?

Thanks.

Posted By Warren / Posted on 11/04/2011 at 3:41 PM


Christian F The code is working fine with Qrcode, but i'm trying to adapt it for Barcode, but doesn't work. Any idea?

Posted By Christian F / Posted on 11/23/2011 at 9:05 PM


Christian F Based on the code above and the zxing client sample code, I tried to create an apps which can read any type of code. But on my device, it's working fine while using Qrcode, but doesn't work with any others type of code, specially Barcode; Where i'm wrong? Here is the code -

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009";
      xmlns:s="library://ns.adobe.com/flex/spark" title="Scanner">
   
   <fx:Script>
      <![CDATA[
         import mx.core.BitmapAsset;
         import com.google.zxing.common.BitMatrix;
         import com.google.zxing.BarcodeFormat;
         import com.google.zxing.BinaryBitmap;
         import com.google.zxing.BufferedImageLuminanceSource;
         import com.google.zxing.DecodeHintType;
         import com.google.zxing.MultiFormatReader;
         import com.google.zxing.Result;
         import com.google.zxing.client.result.ParsedResult;
         import com.google.zxing.client.result.ResultParser;
         import com.google.zxing.common.GlobalHistogramBinarizer;
         import com.google.zxing.common.flexdatatypes.HashTable;
         //import com.google.zxing.oned.EAN13Reader;
         //import com.google.zxing.qrcode.QRCodeReader;
         
         import flashx.textLayout.tlf_internal;
         
         protected var camera:Camera;
         private var videoDisplay:Video = new Video(300, 300);
         private var myReader:MultiFormatReader;
         private var bmd:BitmapData;
         private var cameraStarted:Boolean = false;
         
         
         protected function start_camera(event:MouseEvent):void
         {
            myReader = new MultiFormatReader();
            
            if(!cameraStarted){
               if(Camera.isSupported) {
                  camera = Camera.getCamera();
                  camera.setMode(300, 300, 15);
                  
                  videoDisplay.x = 295;
                  sv.addChild(videoDisplay);
                  
                  videoDisplay.attachCamera(camera);
                  videoDisplay.rotation = 90;
                  
                  btn.label = "Scan Now";
                  lbl.text = "";
                  cameraStarted = true;
               } else {
                  lbl.text = "No camera found";
               }
            } else {
               decodeSnapshot();
            }
         }
         
         public function decodeSnapshot():void {
            lbl.text = "Checking...";
            bmd = new BitmapData(300, 300);
            bmd.draw(videoDisplay, null, null, null, null, true);
            videoDisplay.cacheAsBitmap = true;
            videoDisplay.cacheAsBitmapMatrix = new Matrix;
            decodeBitmapData(bmd, 300, 300);
            bmd.dispose();
            bmd=null;
            System.gc();
         }
         
         public function decodeBitmapData(bmpd:BitmapData, width:int, height:int):void {
            var lsource:BufferedImageLuminanceSource = new BufferedImageLuminanceSource(bmpd);
            var bitmap:BinaryBitmap = new BinaryBitmap(new GlobalHistogramBinarizer(lsource));
            
            var ht:HashTable = null;
            ht = this.getAllHints();
            
            var res:Result = null;
            try {
               res = myReader.decode(bitmap, ht);
            }
            
            catch (event:Error) {
               
            }
            
            if (res == null) {
               videoDisplay.clear();
               lbl.text = "Nothing decoded";
            } else {
               var parsedResult:ParsedResult = ResultParser.parseResult(res);
               lbl.text = parsedResult.getDisplayResult();
               sv.removeChild(videoDisplay);
               cameraStarted = false;
               btn.label = "Start Camera";
            }
            
         }
         
         private function getAllHints():HashTable {
            var ht:HashTable = new HashTable;
            //ht.Add(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.EAN_13);
            return ht;
         }
      ]]>
   </fx:Script>
   <fx:Declarations>
      <!-- Place non-visual elements (e.g., services, value objects) here -->
   </fx:Declarations>
   <s:VGroup height="100%" width="100%" top="0" right="0" bottom="0" left="0" horizontalAlign="center">
      <s:VGroup width="100%" height="300" horizontalAlign="center" id="vg">
         <s:SpriteVisualElement id="sv" width="300" height="200" />
      </s:VGroup>
      <s:VGroup horizontalAlign="center" >
         <s:Button id="btn" width="220" height="36" label="Start Camera"
                click="start_camera(event)"/>
         <s:Label id="lbl" x="106" y="291" text=""/>
      </s:VGroup>
   </s:VGroup>
</s:View>

Posted By Christian F / Posted on 11/24/2011 at 12:51 AM


EC Have you gotten this to work with anything other than code 39? I am running into the same problem. Using multireader or exclusivly using code39 / 128 reader. It does not read anything other than QR codes.

Posted By EC / Posted on 11/29/2011 at 12:11 PM


Cristian Helllo,

I have the same prolem that has Vivek with HashTable, that's the error:

1046: Type was not found or was not a compile-time constant: HashTable

I have zxing projecte in the same way is in code,
import com.google.zxing.

My project folder is src,
so it's on src/com/google.zxing.

All classes are corrctly imported except HashTable .

Any idea?
Thanks,
Best regards

Posted By Cristian / Posted on 01/24/2012 at 2:35 AM


Cristian Hello,

solved!
I started a new project and now it's working,
firstly I was trying to mix my own project with this code,

thanks,
best regards,
Cristian

Posted By Cristian / Posted on 01/24/2012 at 3:10 AM


Cristian Hello again,

I have compiled this to IOS app with FLEX 4 and it's so heavy, 194MG.

That's correcte?

Best regards,
Cristian

Posted By Cristian / Posted on 01/24/2012 at 4:02 AM


iBrent Brian,

Thanks for posting this! It's exactly what I needed.

For everyone struggling with the HashTable compiler error,

It's not really the HashTable causing the problem, it's a direct result of the mx classes that you need to comment out, according to what Brian wrote above. Once you comment out those classes, the error goes away. The compiler is actually throwing errors within other classes that HashTable has dependencies on.

iBrent

Posted By iBrent / Posted on 02/03/2012 at 2:08 PM


ayo Hi guys..
A little help needed here.
Do I need to have a base application on the device before using the zxing lib?

Posted By ayo / Posted on 02/05/2012 at 3:52 PM


Cristian Hello,

I have downloaed zzing 2.0 and I think it works faster but the app still freezing if I loop decodeSnapsho function.

I think the way is not loop decodeSnapsho because is to heavy for mobile app so the way must be another function like ... detectQR..

any idea?
best regards,
Cristian

Posted By Cristian / Posted on 02/11/2012 at 2:16 AM


John Levitras Is there anyone who managed to read any other format except QR? I'm trying for 2 days with no result. Any help, please?
Thanks

Posted By John Levitras / Posted on 02/16/2012 at 6:54 AM


dixit can you please help me zxing configure in iphone app how i dont know

Posted By dixit / Posted on 02/22/2012 at 4:02 AM


Miguel The hashtable compiler error can simply be solved by casting to type int... no need to comment tons of stuff out or mess with dependencies to any great extent or anything. It's a less than one full line of code solution...

Posted By Miguel / Posted on 03/02/2012 at 1:55 PM


Gaurav ak hey, i m getting a blank white screen when i export it as an android apk and run it on my phone. can anyone point the mistake i might be committing, i am using the same code as mentioned above, and in the design view of mxml file i do get a button with label "start camera" but while running on phone, there is a blank white screen

Posted By Gaurav ak / Posted on 03/22/2012 at 10:20 PM


Brian Rinaldi @gaurav - did you ensure that you modified the permissions in the app.xml? I seem to recall a similar problem if the permissions were not properly set.

Posted By Brian Rinaldi / Posted on 03/23/2012 at 6:36 AM


gaurav @brian can you please point out the exact modification which i need to make there because i dont know what to change and where. code written below


<?xml version="1.0" encoding="utf-8" standalone="no"?>
<application xmlns="http://ns.adobe.com/air/application/2.6">;

<!-- Adobe AIR Application Descriptor File Template.

   Specifies parameters for identifying, installing, and launching AIR applications.

   xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/2.6
         The last segment of the namespace specifies the version
         of the AIR runtime required for this application to run.
         
   minimumPatchLevel - The minimum patch level of the AIR runtime required to run
         the application. Optional.
-->

   <!-- A universally unique application identifier. Must be unique across all AIR applications.
   Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. -->
   <id>Main.debug</id>

   <!-- Used as the filename for the application. Required. -->
   <filename>Main</filename>

   <!-- The name that is displayed in the AIR application installer.
   May have multiple values for each language. See samples or xsd schema file. Optional. -->
   <name>Main-debug</name>
   
   <!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade.
   Values can also be 1-part or 2-part. It is not necessary to have a 3-part value.
   An updated version of application must have a versionNumber value higher than the previous version. Required for namespace >= 2.5 . -->
   <versionNumber>0.0.0</versionNumber>
      
   <!-- A string value (such as "v1", "2.5", or "Alpha 1") that represents the version of the application, as it should be shown to users. Optional. -->
   <!-- <versionLabel></versionLabel> -->

   <!-- Description, displayed in the AIR application installer.
   May have multiple values for each language. See samples or xsd schema file. Optional. -->
   <!-- <description></description> -->

   <!-- Copyright information. Optional -->
   <!-- <copyright></copyright> -->

   <!-- Publisher ID. Used if you're updating an application created prior to 1.5.3 -->
   <!-- <publisherID></publisherID> -->

   <!-- Settings for the application's initial window. Required. -->
   <initialWindow>
      <!-- The main SWF or HTML file of the application. Required. -->
      <!-- Note: In Flash Builder, the SWF reference is set automatically. -->
      <content>Main.swf</content>
      
      <!-- The title of the main window. Optional. -->
      <!-- <title></title> -->

      <!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
      <!-- <systemChrome></systemChrome> -->

      <!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
      <!-- <transparent></transparent> -->

      <!-- Whether the window is initially visible. Optional. Default false. -->
      <!-- <visible></visible> -->

      <!-- Whether the user can minimize the window. Optional. Default true. -->
      <!-- <minimizable></minimizable> -->

      <!-- Whether the user can maximize the window. Optional. Default true. -->
      <!-- <maximizable></maximizable> -->

      <!-- Whether the user can resize the window. Optional. Default true. -->
      <!-- <resizable></resizable> -->

      <!-- The window's initial width in pixels. Optional. -->
      <!-- <width></width> -->

      <!-- The window's initial height in pixels. Optional. -->
      <!-- <height></height> -->

      <!-- The window's initial x position. Optional. -->
      <!-- <x></x> -->

      <!-- The window's initial y position. Optional. -->
      <!-- <y></y> -->

      <!-- The window's minimum size, specified as a width/height pair in pixels, such as "400 200". Optional. -->
      <!-- <minSize></minSize> -->

      <!-- The window's initial maximum size, specified as a width/height pair in pixels, such as "1600 1200". Optional. -->
      <!-- <maxSize></maxSize> -->

<!-- The initial aspect ratio of the app when launched (either "portrait" or "landscape"). Optional. Mobile only. Default is the natural orientation of the device -->

<!-- <aspectRatio></aspectRatio> -->

<!-- Whether the app will begin auto-orienting on launch. Optional. Mobile only. Default false -->

<!-- <autoOrients></autoOrients> -->

<!-- Whether the app launches in full screen. Optional. Mobile only. Default false -->

<!-- <fullScreen></fullScreen> -->

<!-- The render mode for the app (either auto, cpu, or gpu). Optional. Mobile only. Default auto -->

<!-- <renderMode></renderMode> -->

      <!-- Whether or not to pan when a soft keyboard is raised or lowered (either "pan" or "none"). Optional. Defaults "pan." -->
      <!-- <softKeyboardBehavior></softKeyboardBehavior> -->
   <autoOrients>true</autoOrients>
<fullScreen>true</fullScreen>
<visible>true</visible>
<softKeyboardBehavior>none</softKeyboardBehavior>
</initialWindow>

   <!-- We recommend omitting the supportedProfiles element, -->
   <!-- which in turn permits your application to be deployed to all -->
   <!-- devices supported by AIR. If you wish to restrict deployment -->
   <!-- (i.e., to only mobile devices) then add this element and list -->
   <!-- only the profiles which your application does support. -->
   <!-- <supportedProfiles>desktop extendedDesktop mobileDevice extendedMobileDevice</supportedProfiles> -->

   <!-- The subpath of the standard default installation location to use. Optional. -->
   <!-- <installFolder></installFolder> -->

   <!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. -->
   <!-- <programMenuFolder></programMenuFolder> -->

   <!-- The icon the system uses for the application. For at least one resolution,
   specify the path to a PNG file included in the AIR package. Optional. -->
   <!-- <icon>
      <image16x16></image16x16>
      <image32x32></image32x32>
      <image36x36></image36x36>
      <image48x48></image48x48>
      <image72x72></image72x72>
      <image114x114></image114x114>
      <image128x128></image128x128>
   </icon> -->

   <!-- Whether the application handles the update when a user double-clicks an update version
   of the AIR file (true), or the default AIR application installer handles the update (false).
   Optional. Default false. -->
   <!-- <customUpdateUI></customUpdateUI> -->
   
   <!-- Whether the application can be launched when the user clicks a link in a web browser.
   Optional. Default false. -->
   <!-- <allowBrowserInvocation></allowBrowserInvocation> -->

   <!-- Listing of file types for which the application can register. Optional. -->
   <!-- <fileTypes> -->

      <!-- Defines one file type. Optional. -->
      <!-- <fileType> -->

         <!-- The name that the system displays for the registered file type. Required. -->
         <!-- <name></name> -->

         <!-- The extension to register. Required. -->
         <!-- <extension></extension> -->
         
         <!-- The description of the file type. Optional. -->
         <!-- <description></description> -->
         
         <!-- The MIME content type. -->
         <!-- <contentType></contentType> -->
         
         <!-- The icon to display for the file type. Optional. -->
         <!-- <icon>
            <image16x16></image16x16>
            <image32x32></image32x32>
            <image48x48></image48x48>
            <image128x128></image128x128>
         </icon> -->
         
      <!-- </fileType> -->
   <!-- </fileTypes> -->

<!-- iOS specific capabilities -->
   <!-- <iPhone> -->
      <!-- A list of plist key/value pairs to be added to the application Info.plist -->
      <!-- <InfoAdditions>
<![CDATA[
<key>UIDeviceFamily</key>
<array>
<string>1</string>
<string>2</string>
</array>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleBlackOpaque</string>
<key>UIRequiresPersistentWiFi</key>
<string>YES</string>
]]>
</InfoAdditions> -->
<!-- <requestedDisplayResolution></requestedDisplayResolution> -->
   <!-- </iPhone> -->

   <!-- Specify Android specific tags that get passed to AndroidManifest.xml file. -->
   <!--<android>
      <manifestAdditions>
      <![CDATA[
         <manifest android:installLocation="auto">
            <uses-permission android:name="android.permission.INTERNET"/>
            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
            <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
            <uses-configuration android:reqFiveWayNav="true"/>
            <supports-screens android:normalScreens="true"/>
            <uses-feature android:required="true" android:name="android.hardware.touchscreen.multitouch"/>
            <application android:enabled="true">
               <activity android:excludeFromRecents="false">
                  <intent-filter>
                     <action android:name="android.intent.action.MAIN"/>
                     <category android:name="android.intent.category.LAUNCHER"/>
                  </intent-filter>
               </activity>
            </application>
         </manifest>
      ]]>
      </manifestAdditions>
   </android> -->
   <!-- End of the schema for adding the android specific tags in AndroidManifest.xml file -->

<android>
<manifestAdditions><![CDATA[
         <manifest android:installLocation="auto">
          <!--See the Adobe AIR documentation for more information about setting Google Android permissions-->
          <!--Removing the permission android.permission.INTERNET will have the side effect
      of preventing you from debugging your application on your device-->
          <uses-permission android:name="android.permission.INTERNET"/>
          <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>-->
          <!--<uses-permission android:name="android.permission.READ_PHONE_STATE"/>-->
          <!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>-->
          <!--The DISABLE_KEYGUARD and WAKE_LOCK permissions should be toggled together
      in order to access AIR's SystemIdleMode APIs-->
          <!--<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>-->
          <!--<uses-permission android:name="android.permission.WAKE_LOCK"/>-->
          <uses-permission android:name="android.permission.CAMERA"/>
          <!--<uses-permission android:name="android.permission.RECORD_AUDIO"/>-->
          <!--The ACCESS_NETWORK_STATE and ACCESS_WIFI_STATE permissions should be toggled
      together in order to use AIR's NetworkInfo APIs-->
          <!--<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>-->
          <!--<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>-->
         </manifest>
         
      ]]></manifestAdditions>
</android>
<iPhone>
<InfoAdditions><![CDATA[
         <key>UIDeviceFamily</key>
         <array>
            <string>1</string>
            <string>2</string>
         </array>
      ]]></InfoAdditions>
<requestedDisplayResolution>high</requestedDisplayResolution>
</iPhone>
</application>

Posted By gaurav / Posted on 03/23/2012 at 6:43 AM


gaurav Just to add on I did checked the android camera permission while starting flex mobile project, and its evident from the xml code.
But another thing that i couldn't understand is that even the button with label start camera is not showing up

Posted By gaurav / Posted on 03/23/2012 at 6:55 AM


Bas help!

public function getAllHints():HashTable
         {
            var ht:HashTable=new HashTable;
            ht.Add(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
            return ht;
         }

ERROR: type was not found as a compile time constant:HashTable

Posted By Bas / Posted on 03/26/2012 at 3:48 AM


Paul Hi

Im implementing the Zing AS3 library here and in com\google\zxing\common\flexdatatypes\HashTable.as, Line 24   get the error

1067: Implicit coercion of a value of type String to an unrelated type int.

Any ideas anyone ?

Posted By Paul / Posted on 04/16/2012 at 9:33 PM


Paul The offending code is;

public function getIndexOf(key:Object):int
      {
         for (var i:String in this._arr)
         {
            if (this._arr[i][0] == key)
            {
               return i;
            }
         }
         return undefined;
      }

Posted By Paul / Posted on 04/16/2012 at 11:18 PM


daniele @paul: simply use instead of "return i;" "return int(i);"

Posted By daniele / Posted on 04/24/2012 at 12:44 PM


Paul Hi Daniele.

Thanks for the answer. Have tried it and it works except that I now have the following errors;

.\ResultParser.as, Line 261 1120: Access of undefined property StringUtil.

and

\ResultParser.as, Line 25 1172: Definition mx.utils:StringUtil could not be found.

Which I am told results because I am trying to use StringUtils which is specific to Flex and not to Flash. Theres a way around this which involves creating and importing into Flash a certain .swc file but I have not yet gotten around to trying that. Anyone else sorted this issue yet?

Thanks

Paul

Posted By Paul / Posted on 04/24/2012 at 11:16 PM


daniele @paul: install the as3 corelib framework (I think it works on flash too). it should work

Posted By daniele / Posted on 04/26/2012 at 8:29 AM


Paul Thanks for that Daniele.

I found that at;

https://github.com/mikechambers/as3corelib/

I dont know how to get it except to copy every file one by one and save into the same file structure as appears in the link. Is there a place where its all downloaded as a single .zip package perhaps.

Sorry to be a pain.

Paul

Posted By Paul / Posted on 04/27/2012 at 12:41 AM


daniele @paul: np. there's a "zip" button on the top left of the page, can you see it?

Posted By daniele / Posted on 04/27/2012 at 12:51 AM


Paul OK !

Got it. Thanks a MILLION.

I will try to get the project going with this.

Paul

Posted By Paul / Posted on 04/27/2012 at 2:14 AM


Paul Hi

I have managed to download the CoreLib thanks and inside the library I found what I think is the missing StrinUtils.as file. Could someone please take a look and confirm that I have the correct file;

https://github.com/mikechambers/as3corelib/blob/24c6c16aecbf0d8fcc043ae671e689b0d4b4c559/src/com/adobe/utils/StringUtil.as

Also I have tried to include it in my project but looking at the package definition in the original file;

package com.adobe.utils

and comparing with where the error seems to be looking for it;

1172: Definition mx.utils:StringUtil could not be found

there is some kind od miss-match here.

If I am right could someone please direct me as to where to place the StrinUtil.as file?

Or have I got it all completely wrong?

Thanks

Paul

Posted By Paul / Posted on 05/03/2012 at 11:18 PM


Laurence MacNeill I haven't been able to get this to work at all, yet... It does display the video, and it does seem to process the data when I click the button, but every time it always returns "nothing decoded." I'm using this on a 5th generation iPod Touch with iOS 5.1, and Flash Builder 4.6. So everything is as up-to-date as possible... And still no decode...

What am I doing wrong? (Yes, I *have* tested the bar-codes I'm trying to scan -- they do work when I scan them with a different program on the same device.)

Any help?

Posted By Laurence MacNeill / Posted on 06/04/2012 at 5:16 PM


Jesper Hi,
Did anyone get this working with barcodes? I'm running it on an iPhone 4S (compiled with Flex 4.6) and QR-code works fine, but not barcodes (tried different hashtable settings and also none)?
Suggestions?

Posted By Jesper / Posted on 07/05/2012 at 5:59 AM


Todd Has anyone had issues with focus? When I start the app I have written, many times the QR code is blurry. It seems autofocus is not working (Android 2.3.4, HTC Thunderbolt). I have had others try the app out on their phones, and the same issue pops up - the preview is blurry. Does anyone have any ideas regarding this? Thanks in advance

Posted By Todd / Posted on 09/29/2012 at 9:16 AM


Arend I wonder if it is possible to make this "production ready" ? From the comments, it might be too slow, and we have problems with auto-focus ?

Regards

Posted By Arend / Posted on 12/08/2012 at 9:22 AM


Jeff Hi guys,

Does this library support continuous scanning instead of touching SCAN NOW button? hope someone can enlighten this info..

Thanks!

Posted By Jeff / Posted on 03/18/2013 at 6:06 PM


Jason Jakob Just create a timer that keeps performance the scan now until a successful decode happens.

Posted By Jason Jakob / Posted on 07/13/2013 at 6:53 PM


Marcio Fermino Friend

I hava error in the line

public function getAllHints():HashTable
         {

Who resolve ?

Posted By Marcio Fermino / Posted on 07/23/2013 at 1:17 PM


Write your comment



(it will not be displayed)







About

My name is Brian Rinaldi and I am the Web Community Manager for Flash Platform at Adobe. I am a regular blogger, speaker and author. I also founded RIA Unleashed conference in Boston. The views expressed on this site are my own & not those of my employer.