Would you like to tell us how we are doing?

You bet No thanks

Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

Barcode scanning

A BlackBerry device with a camera can be used as an image or barcode scanner.

The BlackBerry Java SDK 6.1 includes ZXing 1.6, an open-source barcode scanning library. You can use the classes found in the com.google.zxing package, in conjunction with the net.rim.device.api.barcodelib package, to scan 1-D and 2-D barcodes.

To scan an image for a barcode, you must construct a BarcodeScanner object, and implement a matching decoder and listener. When the camera detects a barcode, it is passed into a BarcodeDecoder object for decoding, using the ZXing library. After the barcode is decoded, it is passed as raw data into a BarcodeScannerListener object for processing.

When decoding a barcode, you have the option of giving the decoder a set of hints. Hints are constants defined in the ZXing library that narrow down the possible results for the decoder, and improve the speed and accuracy of decoding.

The ZXing library also supports encoding of strings into 2-D barcodes. The MultiFormatWriter class generates a ByteMatrix of black and white pixels. You can create more specific implementations using the Writer interface.

Barcode types supported

The following 1-D and 2-D barcode formats are supported by the BlackBerry Java SDK:

  • CODABAR 1D
  • Code 128 1D
  • Code 39 1D
  • Code 93 1D
  • Data Matrix 2D
  • EAN-13 1D
  • EAN-8 1D
  • ITF 1D
  • PDF417
  • QR Code 2D
  • RSS 14
  • RSS EXPANDED
  • UPC-A 1D
  • UPC-E 1D
  • UPC/EAN extension 1D

Code sample: scan a barcode

import java.util.*;

import net.rim.device.api.barcodelib.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.container.*;

import com.google.zxing.*;

//Create a class to run the application by extending UiApplication.
public final class BarcodeScanDemo extends UiApplication
{

//Create the main method that starts the application.
    public static void main(String[] args)
    {
        new BarcodeScanDemo().enterEventDispatcher();
    }

//Create a constructor for the class, and display a BarcodeScanDemoScreen object.
    public BarcodeScanDemo()
    {
        pushScreen(new BarcodeScanDemoScreen());
    }
}

//Define a screen for your class that extends the  MainScreen class.
final class BarcodeScanDemoScreen extends MainScreen
{

//Create a constructor for the screen.
    public BarcodeScanDemoScreen()
    { 

//Create a BarcodeDecoderListener object to handle the data that is 
//received when a barcode is scanned. In it, implement barcodeDecoded() 
//to process the raw data that is sent by the decoder.
        BarcodeDecoderListener listener = new BarcodeDecoderListener()
        {
            public void barcodeDecoded( String rawText )
            {
                // Do something with the raw text
            }
        };

//Create a Hashtable to store decoding hints in.
        Hashtable hints = new Hashtable(1);

//Create a new Vector object  to store barcode formats in.
        Vector formats  = new Vector(1);

//Add the BarcodeFormat.QR_CODE constant to the Vector object using 
//Vector.addElement(Object obj). You can add more than one 
//constant (hint) to a Vector object.
        formats.addElement(BarcodeFormat.QR_CODE);

//Invoke Hashtable.put(Object key, Object value), and add the Vector 
//object to the hash table. The DecodeHintType.POSSIBLE_FORMATS constant 
//is used to specify that the hints contained in the Vector object are 
//barcode formats. Other constants for decoding hints can be found in 
//the com.google.zxing.DecodeHintType class.
        hints.put(DecodeHintType.POSSIBLE_FORMATS, formats);

//Construct a BarcodeDecoder object to decode data received from the 
//camera's viewfinder into usable raw data. Pass the Hashtable object into it.
        BarcodeDecoder decoder = new BarcodeDecoder( hints ); 

//Create a try block, and construct a MainScreen object to contain 
//the camera viewfinder.
        try
        {
            MainScreen screen = new MainScreen();

//Construct a BarcodeScanner object, and pass the BarcodeDecoder and 
//BarcodeListener objects into it. Invoke BarcodeScanner.getVideoControl() 
//to return a VideoControl object. Invoke VideoControl.setDisplayFullScreen(true) 
//to set the video's display to full screen.
            BarcodeScanner scanner = new BarcodeScanner( decoder, listener );
            scanner.getVideoControl().setDisplayFullScreen( true );

//Invoke Screen.add(Field field) to add the barcode scanner's view finder 
//to the screen, then invoke UiApplication.pushScreen(Screen screen) to 
//display the viewfinder.
            screen.add( scanner.getViewfinder() );
            UiApplication.getUiApplication().pushScreen( screen );

//Start the barcode scanner by invoking BarcodeScanner.startScan(). 
//Close the try block.
            scanner.startScan();
        }

//Open a catch block to catch any errors that may occur.
        catch (Exception e)
        {
            // Catch errors here
        }
    }
}

Hints

Hints are constants passed to a BarcodeDecoder object in the form of a Hashtable object which help the decoder interpret the barcode by narrowing down the possibilities of what the image presented could be. In addition to providing specific hints, such as a barcode's format, the DecodeHintType class in the com.google.zxing package specifies types of hints.

Hints are passed into a BarcodeDecoder object as a Hashtable. The data (hints) stored in the Hashtable are interpreted by the DecodeHintType constant passed into the BarcodeDecoder object's constructor.

When implementing a BarcodeDecoder, hints are essential to improving the performance and speed of a barcode scanning application. By narrowing down what the decoder looks for when interpreting an image, the computational power required decreases, and accuracy of reading increases. In most cases, for example, you will not need to scan both 1D and 2D barcodes. If this is the case, then instructing the decoder to only look for 2D barcode formats will reduce the amount of time the decoder needs to find a barcode in a scanned image.

Add a hint to your barcode scanner

  1. Import the required classes.

    import java.util.*;
    
    import net.rim.device.api.barcodelib.*;
    import net.rim.device.api.ui.*;
    import net.rim.device.api.ui.container.*;
    
    import com.google.zxing.*;
  2. Create a Hashtable to store decoding hints in.

       Hashtable hints = new Hashtable();
  3. Create a new Vector object to store barcode formats in.

       Vector formats = new Vector();
  4. Add the BarcodeFormat.QR_CODE constant to the Vector object using Vector.addElement(Object obj). You can add more than one constant (hint) to a Vector object.

       formats.addElement(BarcodeFormat.QR_CODE);
  5. Invoke Hashtable.put(Object key, Object value), and add the Vector object to the hash table. The DecodeHintType.POSSIBLE_FORMATS constant is used to specify that the hints contained in the Vector object are barcode formats. Other constants for decoding hints can be found in the com.google.zxing.DecodeHintType class.

       hints.put(DecodeHintType.POSSIBLE_FORMATS, formats);
  6. Construct a BarcodeDecoder object, passing the Hashtable object into its constructor.

       BarcodeDecoder decoder = new BarcodeDecoder(hints);