Reading QR Codes Using the Mobile Vision API

Introduction

QR codes have become ubiquitous in recent years. I am sure you’ve seen one in a newspaper advertisement or on a billboard. In layman’s terms, QR codes, like all other barcodes, are images that are designed to be read by machines. Usually, they represent a small string, such as a shortened URL or a phone number. Here is a sample QR code that contains the URL of the Tuts+ homepage:

Tuts+ URL as a QR code

Unlike traditional barcodes, which need specialized hardware, QR codes can be read accurately by any smartphone with a decent camera.

The latest release of the Google Play services SDK includes the mobile vision API which, among other things, makes it very easy for Android developers to create apps capable of detecting and reading QR codes in real time. In this tutorial, I am going to help you get started with it.

Prerequisites

To follow this tutorial, you will need:

  • the latest version of Android Studio
  • an Android device with a camera

1. Installing the Google Play Services SDK

Before you use the mobile vision API in your app, you should add the Google Play services SDK 7.8 as a compile dependency in your app module’s build.gradle.

When you press the Sync Now button, you will see an error that looks like this:

Install repository error

Click the Install repository and sync project link to install the SDK.

2. Editing the App Manifest

Add the following line to your app’s AndroidManifest.xml to automatically install the barcode detection libraries on the devices that try to run your app:

Additionally, as you will be using the device’s camera to capture the QR codes, you should request the android.permission.CAMERA permission.

3. Reading a QR Code From a Photo

Let’s now write some code that can read a QR code from a photo stored in your app’s assets folder. I’m going to name the photo myqrcode.jpg. If you don’t have any photos containing QR codes handy, you can get some from Flickr.

Step 1: Convert the Photo Into a Bitmap

Because the mobile vision API needs a Bitmap as its input, you should first convert your photo into a Bitmap. To do so, open the photo using the open method of the AssetManager class and pass the InputStream returned to the decodeStream method of BitmapFactory. To keep it simple, do it inside the onCreate method of your Activity.

Step 2: Create a Barcode Detector

To detect QR codes(and other types of barcodes), you should use an instance of the BarcodeDetector class. The following code shows you how to create one using BarcodeDetector.Builder:

Note that the detector will, by default, detect barcodes of all supported formats. I have used the setBarcodeFormats method to explicitly specify that the detector should only detect QR codes.

Step 3: Read the QR Code

Use Frame.Builder to create a Frame using the Bitmap you created earlier.

Call the detect method of the BarcodeDetector to generate a SparseArray containing all the QR codes the BarcodeDetector detected in your photo.

Each item of the SparseArray contains a Barcode object. To fetch the raw contents of the QR code, you can use the Barcode object’s rawValue field. However, I suggest you use the easier to read displayValue field instead. Here’s some code that prints the contents of the first QR code the API detected:

If you run your Activity now, you should be able to see the message contained in your photo’s QR code.

4. Reading a QR Code Using the Camera

The mobile vision API also makes it very easy for you to detect and read barcodes using your device’s camera in real time. Let’s create a new Activity that does just that.

Step 1: Define the Layout

Create a new layout XML file called activity_main.xml. The layout should have a SurfaceView in order to display the preview frames captured by the camera. If you want, you can also add a TextView to display the contents of the QR codes the API detects.

After using a RelativeLayout to position both widgets, the layout XML file should look something like this:

Step 2: Create the Activity

Create a new Java class called MainActivity.java. Make it a subclass of Activity and override its onCreate method. Inside the onCreate method, call setContentView to apply the layout you created in the previous step. Next, use findViewById to get references to the widgets defined in the layout.

To fetch a stream of images from the device’s camera and display them in the SurfaceView, create a new instance of the CameraSource class using CameraSource.Builder. Because the CameraSource needs a BarcodeDetector, create one using the BarcodeDetector.Builder class. If you want, you can adjust the dimensions of the camera preview using the setRequestedPreviewSize method.

Next, add a callback to the SurfaceHolder of the SurfaceView so that you know when you can start drawing the preview frames. The callback should implement the SurfaceHolder.Callback interface.

Inside the surfaceCreated method, call the start method of the CameraSource to start drawing the preview frames. Because the start method expects you to handle an IOException, you should call it from inside a try...catch block.

Similarly, inside the surfaceDestroyed method, call the stop method of the CameraSource to stop drawing the preview frames.

Your Activity is almost ready. However, you still need to tell the BarcodeDetector what it should do when it detects a QR code. Create an instance of a class that implements the Detector.Processor interface and pass it to the setProcessor method of the BarcodeDetector. Android Studio will automatically generate stubs for the methods of the interface.

Inside the receiveDetections method, get the SparseArray of Barcode objects by calling the getDetectedItems method of the Detector.Detections class. You can now write the code to do something with the detected QR codes, because I have already shown you how to work with SpareArray objects earlier in this tutorial.

Here’s how you can display the QR code’s displayValue in the TextView:

Note that you should embed the call to the setText method inside a call to the post method of the TextView, because receiveDetections does not run on the UI thread. Failing to do so will lead to a runtime error.

You can now compile and run your app. Point your device’s camera to a QR code and you should be able to see the QR code’s contents immediately.

Real time detection

Conclusion

In this tutorial, you learned how to use the mobile vision API to read QR codes from static images as well as from live camera streams. Even though we only worked with QR codes in this tutorial, you can also use the API to read other popular barcode formats such as UPC-A and EAN-13.

To learn more about the mobile vision API, I recommend visiting the API’s documentation.

Tags:

Comments

Related Articles