Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Scanning a Barcode or QR Code with the Google ZXing Barcode Scanner

Published? true
FormatLanguage: WikiFormat

Problem:

You want your App to be able to scan a Barcode or QR Code.

Solution:

Use an Intent to access the scanning functionality exposed by the Google ZXing Barcode Scanner.

Discussion:

One of the great features of Android is how easy it is to tap into existing functionality. Scanning barcodes and Quick Response (QR) codes is a good example. Google have a free scanning App that can be accessed via an Intent; thus an App can easily add scanning functionality, opening up new interface, communication and feature possibilities.

The following program is an example of how to access the Google Barcode Scanner via an Intent. Make sure that the Google Barcode Scanner is installed. Search for Barcode Scanner in Google Play and install it. It's published by the Google ZXing team. ZXing stands for Zebra Crossing (i.e. pedestrian crosswalk) which as they are painted in the U.K. sort of look like barcodes. In the following layout there are three buttons to choose to scan either a QR code, product barcode or something else. There are two TextViews to display the type of barcode scanned and the data it contains.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.scanbarcode.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="QR Code"
        android:id="@+id/butQR"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:onClick="HandleClick" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Product"
        android:id="@+id/butProd"
        android:layout_alignBottom="@+id/butQR"
        android:layout_toRightOf="@+id/butQR"
        android:layout_toEndOf="@+id/butQR"
        android:onClick="HandleClick" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Other"
        android:id="@+id/butOther"
        android:layout_alignBottom="@+id/butProd"
        android:layout_toRightOf="@+id/butProd"
        android:layout_toEndOf="@+id/butProd"
        android:onClick="HandleClick" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Format"
        android:id="@+id/tvStatus"
        android:layout_below="@+id/butQR"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:background="@android:color/black"
        android:textColor="@android:color/white" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Ready"
        android:id="@+id/tvResult"
        android:layout_below="@+id/tvStatus"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

</RelativeLayout>

Depending upon which button is pressed the program puts the relevant parameters into the Intent before starting the ZXing activity and waiting for the result.

package com.example.scanbarcode;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void HandleClick(View arg0) {
        Intent intent = new Intent("com.google.zxing.client.android.SCAN");
        switch(arg0.getId()){
            case R.id.butQR:
                intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
                break;
            case R.id.butProd:
                intent.putExtra("SCAN_MODE", "PRODUCT_MODE");
                break;
            case R.id.butOther:
                intent.putExtra("SCAN_FORMATS", "CODE_39,CODE_93,CODE_128,DATA_MATRIX,ITF,CODABAR");
                break;
        }
        startActivityForResult(intent, 0); //Barcode Scanner to scan for us
    }
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (requestCode == 0) {
            TextView tvStatus=(TextView)findViewById(R.id.tvStatus);
            TextView tvResult=(TextView)findViewById(R.id.tvResult);
            if (resultCode == RESULT_OK) {
                tvStatus.setText(intent.getStringExtra("SCAN_RESULT_FORMAT"));
                tvResult.setText(intent.getStringExtra("SCAN_RESULT"));
            } else if (resultCode == RESULT_CANCELED) {
                tvStatus.setText("Press a button to start a scan.");
                tvResult.setText("Scan cancelled.");
            }
        }
    }
}

Notice how it is possbile to scan for a family of barcodes (using SCAN_MODE) or a specific type of barcode (using SCAN_FORMATS). If you know what type barcode is being decoded than setting a scan format to that single particular type may result in faster decoding (it will not be trying to run through all the barcode decoding algorithms), as in intent.putExtra("SCAN_FORMATS", "CODE_39");. For mutliple SCAN_FORMATS pass a comma separated list, see the example program above.

SCAN_MODE SCAN_FORMATS
QR_CODE_MODE QR_CODE
PRODUCT_MODE EAN_13
EAN_8
UPC_A
UPC_E
RSS_14
RSS_EXPANDED
ONE_D_MODE As for product mode plus...
CODE_39
CODE_93
CODE_128
ITF
CODABAR
DATA_MATRIX_MODE DATA_MATRIX
AZTEC_MODE AZTEC (beta)
PDF417_MODE PDF_417 (beta)

Now go and make that scanning inventory control or grocery list App you've been thinking of!

See Also:

[1]

[2]

Download:

The source code for this project can be downloaded from http://tekeye.uk/android/examples/download/scanbarcode.zip.