๐ท 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
- SurfaceView & CameraSource
– SurfaceView: Renders the live camera preview.
– CameraSource: Controls the camera feed and feeds frames into the BarcodeDetector. - BarcodeDetector
– Set to detect all barcode formats using Barcode.ALL_FORMATS. - Permissions
– Checks for camera permission before starting the camera. Requests it if not already granted. - ToneGenerator
– A beep sound plays every time a barcode is successfully detected. - 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 usingpost()
for safe rendering. - 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!