๐Ÿ“ท Build a Barcode Scanner App in Android Studio Using Java (with Source Code & Explanation)

If you’re searching for a simple yet powerful way to create a Barcode Scanner App in Android Java using Android Studio, you’re in the right place! This tutorial will guide you through building a fully functional barcode and QR code scanner using Googleโ€™s Mobile Vision API and Androidโ€™s CameraSource class.

This project is ideal for retail apps, inventory management systems, attendance apps, and more.

โœ… Features of This Barcode Scanner App

  • Real-time barcode scanning using device camera
  • Supports all barcode formats (QR, UPC, Data Matrix, etc.)
  • Auto-focus enabled for accurate scanning
  • Audio beep tone when a barcode is detected
  • Displays decoded data in a TextView

๐Ÿ› ๏ธ Tools & Setup Requirements

  • Android Studio
  • Java language
  • Minimum SDK: 21 (Lollipop)
  • Dependencies:
implementation 'com.google.android.gms:play-services-vision:20.1.3'

๐Ÿ“„ Full Java Code for Barcode Scanner (MainActivity.java)

public class MainActivity extends AppCompatActivity {

    private SurfaceView surfaceView;
    private BarcodeDetector barcodeDetector;
    private CameraSource cameraSource;
    private static final int REQUEST_CAMERA_PERMISSION = 201;
    private ToneGenerator toneGen1;
    private TextView barcodeText;
    private String barcodeData;

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

        toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
        surfaceView = findViewById(R.id.surface_view);
        barcodeText = findViewById(R.id.barcode_text);

        initialiseDetectorsAndSources();
    }

    private void initialiseDetectorsAndSources() {
        barcodeDetector = new BarcodeDetector.Builder(this)
                .setBarcodeFormats(Barcode.ALL_FORMATS)
                .build();

        cameraSource = new CameraSource.Builder(this, barcodeDetector)
                .setRequestedPreviewSize(640, 480)
                .setAutoFocusEnabled(true)
                .build();

        surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                        cameraSource.start(surfaceView.getHolder());
                    } else {
                        ActivityCompat.requestPermissions(MainActivity.this,
                                new String[]{Manifest.permission.CAMERA},
                                REQUEST_CAMERA_PERMISSION);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {}

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
                cameraSource.stop();
            }
        });

        barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
            @Override
            public void release() {}

            @Override
            public void receiveDetections(@NonNull Detector.Detections<Barcode> detections) {
                final SparseArray<Barcode> barcodes = detections.getDetectedItems();

                if (barcodes.size() != 0) {
                    barcodeText.post(() -> {
                        if (barcodes.valueAt(0).email != null) {
                            barcodeData = barcodes.valueAt(0).email.address;
                        } else {
                            barcodeData = barcodes.valueAt(0).displayValue;
                        }

                        barcodeText.setText(barcodeData);
                        toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP, 150);
                    });
                }
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        Objects.requireNonNull(getSupportActionBar()).hide();
        cameraSource.release();
    }

    @Override
    protected void onResume() {
        super.onResume();
        Objects.requireNonNull(getSupportActionBar()).hide();
        initialiseDetectorsAndSources();
    }
}

๐Ÿ” Code Explanation

  1. SurfaceView & CameraSource
    – SurfaceView: Renders the live camera preview.
    – CameraSource: Controls the camera feed and feeds frames into the BarcodeDetector.
  2. BarcodeDetector
    – Set to detect all barcode formats using Barcode.ALL_FORMATS.
  3. Permissions
    – Checks for camera permission before starting the camera. Requests it if not already granted.
  4. ToneGenerator
    – A beep sound plays every time a barcode is successfully detected.
  5. Barcode Processing
    – If the barcode contains an email, itโ€™s extracted separately; otherwise, the display value is shown.
    – Data is updated on the UI thread using post() for safe rendering.
  6. Preview Size
    – Set using .setRequestedPreviewSize(640, 480) for balance between quality and performance.

๐Ÿ“ UI Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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"
    tools:context=".MainActivity">

    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="480dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/barcode_text"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        app:layout_constraintTop_toBottomOf="@id/surface_view"
        android:layout_marginTop="50dp"
        android:text="Barcode Text"
        android:textSize="25sp"
        android:padding="5dp" />

</androidx.constraintlayout.widget.ConstraintLayout>

๐Ÿ”’ Important Permissions (AndroidManifest.xml)

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />

โœ… Conclusion

This guide helped you build a real-time barcode scanner app using Java in Android Studio. You learned how to use SurfaceView, CameraSource, BarcodeDetector, and handle permissions, audio tones, and camera lifecycle.

You can expand this app by:

  • Saving scanned data to a database
  • Opening URLs directly from QR codes
  • Switching between front and back camera

Output


๐Ÿ“ฅ Click here to Download The source code or ask questions in the comments below!

Leave a Comment

Your email address will not be published. Required fields are marked *