Adding the RedLaser SDK to your Project
The RedLaser SDK is partly a Java library and partly a native ARM library. Before you start to code your new scanning activity, you’ll need to do some project set up.
The RedLaser SDK requires API level 7. If you are producing an application that runs on API levels earlier than that, you will need to not call the SDK (other than calling checkReadyStatus()) on pre-7 devices.
There’s only 2 files that are absolutely required to get up and running: the jar file containing the Java libraries, and the .so file that contains the native code.
- RedLaser_SDK_Files/libs/armeabi/libredlaser.so (not required to be on build path in order to compile as long as it is added to this directory)
You’ll be limited to 25 scans per device unless you also include a license file. If you’re a licensee and don’t want to use the SDK in evaluation mode, generate a license file for your app at http://redlaser.com/developers and place it at:
The public parts of the SDK have Javadoc documentation describing them. The Javadocs are located in “RedLaser_SDK_Files/Javadocs”. Those docs may be browsed as HTML, or you can import them into Eclipse and use them as tooltips. To set up the Javadocs in Eclipse:
- Set up your project with redlasersdk.jar as an included library.
- Right click on the project and select “Build Path -> Configure Build Path”.
- Select Java Build from the left column and make sure the Libraries tab is selected on the right.
- Expand the redlasersdk.jar entry.
- Select Javadoc location and press the edit button.
- Set the Javadoc URL to “<local path>/RedLaser_SDK_Files/Javadocs”.
- Press the validate button before pressing OK to make sure the location is valid.
The SDK package contains a set of image and layout assets that your application may use as part of the app-supplied overlay. These assets support an overlay similar to the one used by the RedLaser application. The SDK itself does not use these files. You may use these files as a starting point for your own designs.
All designs must include the “redlaser_logo.png” image image in the scanning overlay screen. This file may be renamed or converted to a different format, but must otherwise remain unchanged.
The RedLaser Android SDK requires the following permissions be set in your application’s manifest:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
ACCESS_NETWORK_STATE and INTERNET are both required by the SDK for validating the license. Your app will not run without these.
The RedLaser SDK can be used with or without a license file. With no license file, the SDK runs in evaluation mode, and limits the number of scans per device. The limitations imposed when a license file is present depend on your licensing terms. To find out more details, or to purchase a developer or production license, go to the RedLaser developer site.
When you sign up as a developer, you can generate a license file named “RedLaser_License.xml” from the RedLaser developer portal. You will need to add this file to your project in the /assets/ folder.
The license file is digitally signed. Do not modify it. Any modifications, including changing line-endings (which are sometimes invisibly altered by source control systems) will cause the license to fail. If you run into any issues, download a new copy of your license file and compare to your included version to ensure no changes have occurred.
Your license file has a list of all application root class names you have registered in the RedLaser developer portal. The SDK will only work correctly in licensed mode if it’s being used in one of the applications you’ve registered–that is, if the application’s root class name matches one of the entries in the license file. Your application’s root class name can be found in its “AndroidManifest.xml” file, as the value for the “package” key.
Using the RedLaser SDK in Your App
Much of the documentation describing individual classes, methods, and fields can be found in the Javadoc. This section of documentation will focus on explaining in larger terms how the SDK can fit into your application.
Before You Use the SDK
The first call your application should make to the SDK is a call to RedLaserExtras.checkReadyStatus(). This method performs several checks to see if the SDK can be run successfully. If this method returns any value other than “EvalModeReady” or “LicensedModeReady” you should not attempt to use the SDK. Most likely, your app should disable the button that launch the scanning Activity.
Be sure to use this call instead of performing checks yourself. The SDK currently requires API level 7, but that may change in the future. If it does, checkReadyStatus() will be updated to check for the new minimum–but your code may not.
The SDK will show alerts to the user if its activity is launched but it cannot scan–for example, if it’s opened on a device that has no camera. These alerts, however, are a fallback position–they’re not localized, and may not provide the user with the best experience. Therefore, it’s better for your app to take appropriate action beforehand.
Supported Barcode Types
Here’s the full list of barcode types supported by the SDK. This list is from the BarcodeTypes class:
public static final int NONE = 0x0;
public static final int EAN13 = 0x1;
public static final int UPCE = 0x2;
public static final int EAN8 = 0x4;
public static final int STICKYBITS = 0x8;
public static final int QRCODE = 0x10;
public static final int CODE128 = 0x20;
public static final int CODE39 = 0x40;
public static final int DATAMATRIX = 0x80;
public static final int ITF = 0x100;
public static final int CODE93 = 0x200;
public static final int RSS14 = 0x400;
public static final int CODABAR = 0x800;
public static final int EAN5 = 0x1000;
public static final int EAN2 = 0x2000;
If you’re new to working with barcodes, there’s a good chance you’re looking to scan UPC codes, and are about to choose UPCE. You probably want to look at EAN13 instead. EAN-13 is a newer standard that is a strict superset of the UPC-A standard. You might want to scan UPC-E barcodes as well, just realize that UPC-E barcodes are the 6-digit shortened barcodes found on some products, not the 12 digit codes which are more common.
The “Notes on Specific Barcode Types” section (below) has more specific notes on individual barcode types.
Besides holding the list of supported barcode types, the BarcodeTypes class contains methods for telling the SDK which types you want to find.
Setting up your Activity
Your scan activity should extend the BarcodeScanActivity class. Initiate your scan activity by creating an Intent for it and calling startActivityForResult(). You do not need to put any extra information into the Intent, although the Sample app does this as a means of passing data to its own onCreate() method.
There are 3 main things your activity should do in its onCreate() method:
- Be sure to call super.onCreate().
- Call setContentView() or similar to attach your overlay layout.
- Set the enabledTypes member of BarcodeScanActivity to the types of barcodes you want to look for.
By default, the SDK will add the Camera preview view during onStart(), and will place the Camera preview behind all other children of the root view. The preview view will be sized to match the size of the Activity (generally this means fullscreen).
If you want a more involved layout, you can directly specify a view in your hierarchy to be the ‘container’ view for the camera preview. The SDK will then create a camera preview sized so that it minimally covers all the pixels in the requested view, while maintaining the proper aspect ratio. This setup is particularly useful for tablet devices, where applications may want to use half the screen for camera preview and show live information about scanned items on the other half of the screen.
To specify a view to be the ‘container’ view for the camera preview, you can either set the Tag (not the ID!) of a view to the string “RedLaser Camera Preview Tag”, or you can implement the getPreviewView() method and return the view to be used. Either way, this must be done before onStart() is called. The container view for the Camera preview must be a FrameLayout.
Implementing Callback Methods
There are several methods you should implement in your BarcodeScanActivity subclass in order to receive status updates:
protected abstract void onScanStatusUpdate(HashMap<String, Object> scanStatus)
This callback method is where you receive scan result data. It gets called every 0.2 seconds while scanning is active, whether there is anything new to report or not. This method will continue to be called until doneScanning() or finish() are called. The doneScanning() method ends the scan session and returns the found barcodes as an activity result.
Why a HashMap, instead of multiple parameters? We can extend the HashMap with more keys later, without breaking the API. Clients that want to use features provided by new keys can do so, those that don’t need the new features need not change their code.
The following are the keys to what is stored in the HashMap:
|FoundBarcodes||HashSet<BarcodeResult>||A HashSet of BarcodeResult objects containing all found barcodes in this scan session. The set will be empty if no barcodes have been found yet.|
|NewFoundBarcodes||HashSet<BarcodeResult>||A HashSet of BarcodeResult objects containing any new barcodes that were recognized in the most recent scan pass.A newly found barcode will appear in this set for exactly one call to onScanStatusUpdate(). It will be returned as part of the FoundBarcodes set on that and all future calls.|
|InRange||Boolean||A boolean set to TRUE if there is a barcode in range in the viewfinder. This key may be used to advise the user to hold the phone steady while a barcode is read. Not all devices require this guidance in order to successfully read barcodes – be sure to test on non-focusing cameras to see this key in use.|
|Guidance||Integer||An integer value. This key only exists if there is guidance to be given.1 means that the SDK sees a likely barcode in range, but has not been able to decode it for several seconds. The overlay may use this to advise the user to try scanning the barcode in parts by holding the phone close to each part of the barcode.2 means that the SDK has scanned the first part of a barcode, the contents of which are available in the PartialBarcode property. The overlay may use this to advise the user of the part of the barcode that has been successfully scanned.|
|PartialBarcode||BarcodeResult||A BarcodeResult object containing the part of the barcode that’s been scanned while doing partial scanning. The overlay may show the partially scanned barcode text to the user to help guide them on completing the partial scan.|
|CameraSnapshot||byte||Image data of a scanned barcode. The contents of this field is JPEG data in a byte array. To decrease overhead, this field is not returned on every status update. To obtain this data, call requestImageData() in the extended class of BarcodeScanActivity. Once requestImageData() is called, the camera snapshot data will be returned in a future onStatusUpdate().|
Notes on the InRange Key
The purpose of the inRange key is to let the overlay know when it should be guiding the user to hold their device steady to get a good read of a barcode. This is important for one of our recognition algorithms. The algorithm tries to ensure that it performs its analysis on a frame that has low motion blur, and it uses inter-frame differencing to find such a frame. In this case, guiding the user to hold the device steady is an important part of the process.
Other recognition algorithms, which run at the same time, don’t work in this way. They use a single frame analysis model, and are never in a state where they are confident a barcode is visible in the camera view but don’t know what the barcode’s value is. Because of this, it is entirely possible to have barcodes discovered and BarcodeResults returned without ‘inRange’ ever being set.
Your app should not use ‘inRange’ as a hint that a barcode is about to be found, nor should your overlay rely on entering the ‘inRange’ state before being informed of a newfound barcode.
protected void onError(int error);
Override this method to be notified of Camera errors during scanning. The error codes that may be returned by this method are the error codes defined in android.hardware.Camera.
public String getOrientationSetting();
Override this method to specify whether you want the scan screen overlay to be displayed in portrait or landscape mode. Use the values BarcodeScanActivity.PREF_ORIENTATION_PORTRAIT and BarcodeScanActivity.PREF_ORIENTATION_LANDSCAPE. By default, the orientation is set to portrait.
protected FrameLayout getPreviewView();
Override this method to return the FrameLayout that should be used for the camera preview view. If you don’t override this method, the camera preview will be created as a fullscreen view behind all the other top level views in the activity.
On devices that have a LED light, ‘torch mode’ may be enabled or disabled while scanning by calling setTorch(bool).
Your application may request a snapshot of the preview image by calling requestImageData() while the preview is running. This is an asynchronous method that will return image data in the CameraSnapshot key in a future call to onScanStatusUpdate(). Depending on the device and OS version, this method may take a picture using the camera or it may compress an image from the preview stream. In either case, the returned data is a JPEG image in a byte array.
Should your activity have a need to, the set of enabled barcode types can be changed while scanning.
Ending the Scan Activity
Call finish() or doneScanning() to end the scan session. doneScanning() is a convenience method that creates a return Intent with the scan results. In your calling Activity, look for the RESULT_EXTRA key in the return Intent, as defined in BarcodeScanActivity. The results returned will be an ArrayList<BarcodeResult>.
protected void doneScanning()
If you want to find a single barcode and return, you can put code like the following in your onStatusUpdate() method:
Set<BarcodeResult> allResults = (Set<BarcodeResult>)
if (allResults != null && allResults.size() > 0)
Note that even if you do this, you are not guaranteed to only have a single barcode returned; it is possible for multiple barcodes to be found on the same scan pass and all of them will be returned at once.
Dealing with Scan Results
The SDK reports found barcodes using instances of the BarcodeResult class.
This object contains information about one barcode that has been recognized. Collections of BarcodeResults are returned in the FoundBarcodes and NewFoundBarcodes keys of the HashMap parameter to onScanStatusUpdate() and also as the ArrayList of results returned in the return Intent when doneScanning() is called.
BarcodeResults tell you more than the kind of barcode that was scanned and what the barcode string is. The SDK also returns information about when the barcode was last recognized, where it was found onscreen (yes, you can do simple Augmented Reality with this), as well as associating EAN-5 and EAN-2 extended barcodes with their parents.