Qr Code Scanner Android Studio Tutorial

Step by step guide to building a barcode scanning application using Android Sanggar.

What is this article about

This article will guide you through creating an android application using which you can make use of your mobile camera to scan a barcode and read the data in them.

Prerequisite

  1. The latest version of Android Studio installed. ( download from here )
  2. A mobile device to test the application. (you can make use of the inbuild android emulator but in some pc, it may cause some issues.)
  3. Knowledge of java or any object-oriented programing language.

Let’s write some code

  1. Create a new application in android studio and name it Barcode Scanner.
  2. Open up your app-level Gradle file and add the below dependency there.
        implementation 'com.google.android.gms:play-services-vision:11.0.2'
      

3. Now hit on Sync now button and wait for the build to complete. Once the build is complete open up your manifest file and add the necessary permissions.

        <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />

also, add the metadata field in your manifest file, inside the application tag and above the activity tag.

        <meta-data
android:name="com.google.android.gms.vision.DEPENDENCIES"
android:value="barcode" />

here’s a full view of my manifest file

        <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.barcodescanner">

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />

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

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:merek="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">

<!--<provider
&lt;!&ndash;android:name="androidx.core.content.FileProvider"
android:authorities="com.example.barcodescanner.fileprovider"
android:exported="false"
android:grantUriPermissions="true">&ndash;&gt;

</provider>-->
<meta-data
android:name="com.google.android.gms.vision.DEPENDENCIES"
android:value="barcode" />

<activity android:name=".MainActivity">
<intent-tapis>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

4. Now you have set up all the dependency needed for the barcode scanner to work and all the permission necessary. Let’s build the UI for the app.

5. Open your activity_main.xml file and write the below code inside.

        <?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="300dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="100dp"
/>

<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>

Now your view should look something like this

here we have something called a sufaceview in android and a textview field to display the text scanned by the barcode.

SurfaceView: It provides a dedicated drawing surface embedded inside the view hierarchy.

You have completed the UI code for the Barcode App, now let’s write the java code to make wonders happen.

6. Open MainActivity.java file and you will see the following code.

        public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

let’s add some code of our own

7. First, we need to bind the views.

        public class MainActivity extends AppCompatActivity {

private SurfaceView surfaceView;
private BarcodeDetector barcodeDetector;
private CameraSource cameraSource;
private static final int REQUEST_CAMERA_PERMISSION = 201;
//This class provides methods to play DTMF tones
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);
}

8. Now we will write the method to scan the image for a barcode.

        private void initialiseDetectorsAndSources() {

//Toast.makeText(getApplicationContext(), "Barcode scanner started", Toast.LENGTH_SHORT).show();

barcodeDetector = new BarcodeDetector.Builder(this)
.setBarcodeFormats(Barcode.ALL_FORMATS)
.build();

cameraSource = new CameraSource.Builder(this, barcodeDetector)
.setRequestedPreviewSize(1920, 1080)
.setAutoFocusEnabled(true) //you should add this feature
.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.tiba(surfaceView.getHolder());
} else {
ActivityCompat.requestPermissions(MainActivity.this, new
String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
}

} catch (IOException e) {
e.printStackTrace();
}

}

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

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

barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
@Override
public void release() {
// Toast.makeText(getApplicationContext(), "To prevent memory leaks barcode scanner has been stopped", Toast.LENGTH_SHORT).show();
}

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

barcodeText.post(new Runnable() {

@Override
public void run() {

if (barcodes.valueAt(0).email != null) {
barcodeText.removeCallbacks(null);
barcodeData = barcodes.valueAt(0).email.address;
barcodeText.setText(barcodeData);
toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP, 150);
} else {

barcodeData = barcodes.valueAt(0).displayValue;
barcodeText.setText(barcodeData);
toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP, 150);

}
}
});

}
}
});
}

this method will help us scan and display the text in the textview we created in the XML file.

9. The complete java code will look something like this.

        package com.example.barcodescanner;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;

import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;

import java.io.IOException;

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() {

//Toast.makeText(getApplicationContext(), "Barcode scanner started", Toast.LENGTH_SHORT).show();

barcodeDetector = new BarcodeDetector.Builder(this)
.setBarcodeFormats(Barcode.ALL_FORMATS)
.build();

cameraSource = new CameraSource.Builder(this, barcodeDetector)
.setRequestedPreviewSize(1920, 1080)
.setAutoFocusEnabled(true) //you should add this feature
.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.tiba(surfaceView.getHolder());
} else {
ActivityCompat.requestPermissions(MainActivity.this, new
String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
}

} catch (IOException e) {
e.printStackTrace();
}

}

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

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

barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
@Override
public void release() {
// Toast.makeText(getApplicationContext(), "To prevent memory leaks barcode scanner has been stopped", Toast.LENGTH_SHORT).show();
}

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

barcodeText.post(new Runnable() {

@Override
public void run() {

if (barcodes.valueAt(0).email != null) {
barcodeText.removeCallbacks(null);
barcodeData = barcodes.valueAt(0).email.address;
barcodeText.setText(barcodeData);
toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP, 150);
} else {

barcodeData = barcodes.valueAt(0).displayValue;
barcodeText.setText(barcodeData);
toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP, 150);

}
}
});

}
}
});
}

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

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

}

Now try scanning this barcode and you will see the value that is embedded in the barcode in the textview.

The final screen should something like this.

Thank you.

Source: https://medium.com/analytics-vidhya/creating-a-barcode-scanner-using-android-studio-71cff11800a2