Using ZXing to create an Android barcode scanning app

Learn using zxing to create an android barcode scanning app with practical examples, diagrams, and best practices. Covers android, barcode, barcode-scanner development techniques with visual explan...

Building an Android Barcode Scanner with ZXing

An Android phone scanning a barcode, illustrating the use of ZXing library.

Learn how to integrate the powerful ZXing library into your Android application to create a robust and efficient barcode and QR code scanning solution.

Barcode and QR code scanning capabilities are essential for many modern Android applications, from inventory management to retail and event ticketing. The ZXing (Zebra Crossing) library is a popular, open-source, multi-format 1D/2D barcode image processing library implemented in Java, with ports to other languages. This article will guide you through the process of integrating ZXing into your Android project to build a functional barcode scanner.

Setting Up Your Android Project

Before we dive into the scanning logic, you need to set up your Android project and include the necessary ZXing dependencies. We'll use the zxing-android-embedded library, which provides a convenient wrapper around the core ZXing library, simplifying integration with Android's camera and UI.

1. Step 1: Create a New Android Project

Open Android Studio and create a new project with an 'Empty Activity' template. Choose a suitable name and package for your application.

2. Step 2: Add ZXing Dependency

Open your app-level build.gradle file and add the zxing-android-embedded dependency. Ensure you use the latest stable version.

dependencies {
    implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
}

Adding the ZXing Android Embedded dependency to build.gradle

Implementing the Scanner Activity

The zxing-android-embedded library provides a CaptureActivity that handles camera preview, barcode detection, and result processing. You can either use this activity directly or customize it. For simplicity, we'll start by launching the default scanner.

sequenceDiagram
    participant User
    participant App
    participant ZXingLibrary

    User->>App: Tap 'Scan Barcode' button
    App->>ZXingLibrary: Initiate BarcodeIntent
    ZXingLibrary-->>App: Request Camera Permission
    App->>User: Prompt for Camera Permission
    User->>App: Grant Permission
    App->>ZXingLibrary: Camera Preview Starts
    ZXingLibrary->>ZXingLibrary: Scan for Barcode
    ZXingLibrary-->>App: Barcode Scanned (Result)
    App->>User: Display Scan Result

Flow of initiating a barcode scan using ZXing

To launch the scanner, you'll typically create an Intent and start the CaptureActivity. The result will be returned to your calling activity via onActivityResult.

import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private TextView resultTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        resultTextView = findViewById(R.id.resultTextView);
        Button scanButton = findViewById(R.id.scanButton);

        scanButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startScanner();
            }
        });
    }

    private void startScanner() {
        IntentIntegrator integrator = new IntentIntegrator(this);
        integrator.setPrompt("Scan a barcode or QR code");
        integrator.setOrientationLocked(false); // Allow orientation changes
        integrator.initiateScan();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
        if (result != null) {
            if (result.getContents() == null) {
                Toast.makeText(this, "Scan Cancelled", Toast.LENGTH_LONG).show();
                resultTextView.setText("Scan Cancelled");
            } else {
                Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
                resultTextView.setText("Scanned: " + result.getContents());
            }
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }
}

MainActivity.java: Initiating the scanner and handling results

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="16dp"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/scanButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Scan Barcode" />

    <TextView
        android:id="@+id/resultTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="Scan result will appear here" />

</LinearLayout>

activity_main.xml: Layout for the main activity

Customizing the Scanner Experience

While the default CaptureActivity is functional, you might want to customize the scanner's appearance or behavior. IntentIntegrator offers several methods to configure the scan, such as setting the prompt text, specifying desired barcode formats, or enabling/disabling beep sounds.

integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE); // Scan only QR codes
integrator.setPrompt("Align QR code within the viewfinder");
integrator.setBeepEnabled(false); // Disable beep sound on scan
integrator.setBarcodeImageEnabled(true); // Save barcode image to cache
integrator.initiateScan();

Customizing scanner options with IntentIntegrator