You can find barcodes and QR codes in a lot of places. Their primary purpose is storing data and making it available. While barcodes are more commonly used for basic identification and tracking, QR codes are much more versatile. You have probably seen QR codes that you can scan to visit different URLs. This tactic is used very often for marketing new products or providing promotional links for sales and deals at different outlets. QR codes are also pretty handy when you want to use them for making payments through mobile devices. You just scan the vendor QR code with your mobile and authorize the payment.
In this tutorial, you'll learn how to integrate a barcode reader and a QR code scanner in an Android app. The Google code scanner API will be of immense help here—it will do a lot of heavy lifting for us.
Our app will have a button that users can click to scan QR codes or barcodes. We will create a scanner object and attach listeners that will handle the success or failure of the scanning operation.
Initial Setup
Begin by creating a new project in Android Studio, and name it BarcodeScanner. Set the Language to Kotlin and the Minimum SDK to API 21. This will make sure that our app will run on over 99% of devices.
You can now click on the Finish button.
The primary reason for setting the minimum SDK to 21 is that the code scanner API only works on Android API level 21 and above. Using the Google code scanner API makes the process of creating a barcode scanner app straightforward. This is because you won't have to write any code to properly scan any barcode or QR code. All that will be handled by the API. You will simply get the final result of the scan.
Another advantage of using the API is that you don't have to worry about requesting camera permission.
You should now head over to the settings.gradle file in your project. Make sure that you include Google's Maven repository and Maven central repository in the dependencyResolutionManagement
block as shown below:
1 | dependencyResolutionManagement{ |
2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) |
3 | repositories{ |
4 | google() |
5 | mavenCentral() |
6 | } |
7 | } |
These will be included by default if you are using a recent version of Android Studio.
Now, you will need to modify the app/build.gradle file to include the following dependency:
1 | dependencies{ |
2 | implementation'com.google.android.gms:play-services-code-scanner:16.0.0' |
3 | } |
Leave any other dependencies in the block untouched.
Finally, update your AndroidManifest.xml file to have the following lines:
1 | <meta-data |
2 | android:name="com.google.mlkit.vision.DEPENDENCIES" |
3 | android:value="barcode_ui"/> |
In this case, the meta-data
element should be a child of the application
element so that this information stays associated with the entire application.
We are using it to provide a value for the com.google.mlkit.vision.DEPENDENCIES key. This value determines the model that will be downloaded automatically after app installation. It can have several possible values such as ocr, barcode, and barcode_ui. With the Google code scanner API, we simply set the value to barcode_ui.
Creating the App Layout
Our app will only have two widgets: a TextView
widget that will store the result of the scan and a Button
widget that users can press to start the scan. You can use the following XML to add these two elements to your app layout:
1 | <TextView |
2 | android:id="@+id/barcode_value" |
3 | android:layout_width="wrap_content" |
4 | android:layout_height="wrap_content" |
5 | android:text="Waiting for Scan" |
6 | android:textSize="18sp" |
7 | app:layout_constraintBottom_toBottomOf="parent" |
8 | app:layout_constraintEnd_toEndOf="parent" |
9 | app:layout_constraintStart_toStartOf="parent" |
10 | app:layout_constraintTop_toTopOf="parent"/> |
11 | |
12 | <Button |
13 | android:id="@+id/button" |
14 | android:layout_width="wrap_content" |
15 | android:layout_height="wrap_content" |
16 | android:text="Scan Code" |
17 | android:onClick="scanCode" |
18 | android:textSize="18sp" |
19 | android:layout_marginTop="20sp" |
20 | app:layout_constraintEnd_toEndOf="parent" |
21 | app:layout_constraintStart_toStartOf="parent" |
22 | app:layout_constraintTop_toBottomOf="@id/barcode_value"/> |
There are two noteworthy things here. The first is the android:id
attribute of the TextView
and Button
widget. This id will be useful when we want to reference the elements in our Kotlin code. The second is the android:onClick
attribute, which is set to scanCode
. This means that we will have to declare a public method scanCode()
that accepts a single parameter of type View
.
Implementing the Scan Functionality
We will now define the scanCode()
method that handles the button click. This method will initialize and set up the scanner for us. After that, we will add listeners for the scanner so that we can handle the success, failure, and cancellation of the scan.
Here is our implementation of this method:
1 | funscanCode(view:View){ |
2 | |
3 | valoptions=GmsBarcodeScannerOptions.Builder() |
4 | .setBarcodeFormats( |
5 | Barcode.FORMAT_QR_CODE, |
6 | Barcode.FORMAT_EAN_13) |
7 | .build() |
8 | |
9 | valscanner=GmsBarcodeScanning.getClient(this,options) |
10 | valbarcodeValue=findViewById<TextView>(R.id.barcode_value) |
11 | |
12 | scanner.startScan() |
13 | .addOnSuccessListener{barcode-> |
14 | valrawValue:String?=barcode.rawValue |
15 | barcodeValue.text=rawValue |
16 | |
17 | if(barcode.valueType==Barcode.TYPE_URL){ |
18 | valbrowserIntent=Intent(Intent.ACTION_VIEW,Uri.parse(rawValue)) |
19 | startActivity(browserIntent) |
20 | } |
21 | } |
22 | .addOnCanceledListener{ |
23 | barcodeValue.text="Scan Cancelled" |
24 | } |
25 | .addOnFailureListener{e-> |
26 | Toast.makeText(this,"Barcode scanning failed",Toast.LENGTH_SHORT).show() |
27 | } |
28 | } |
The scanner in this app will only be used to scan the barcodes from beverages and QR codes for links. Therefore, we can make our barcode detector faster by configuring it to only detect these two formats. The setBarcodeFormats()
method does this work for us beautifully. After that, we call the build()
method to build our GmsBarcodeScannerOptions
object and store it as options
.
This object comes in handy when we are instantiating our GmsBarcodeScanner
. We pass the options we stored earlier as the second parameter of the getClient()
method. We also store a reference to our TextView
widget inside the variable barcodeValue
. We will update the text of this widget with the results of the scan.
We are now ready to start our scan. This requires a call to the startScan()
method. We attach three listeners to our scanner.
The addOnSuccessListener
is triggered when the code has been scanned successfully. Inside the listener, we get the raw value of the scanned barcode using rawValue
. This value is assigned to the text
property of the barcodeValue
TextView
widget. If the valueType
matches a URL, we go a step further and open the returned link in the default browser.
The addOnCancelListener
is triggered if you cancel the scan before its successful completion. In this case, we display the message Scan Cancelled inside our TextView
.
In the end, addOnFailureListener
is triggered if the scan fails. We are simply displaying a Toast message in this case.
Try scanning the following QR code, which points to https://code.tutsplus.com/tutorials.
Final Thoughts
In this tutorial, we learned how to create a barcode reader or a QR code scanner in Android. The process has become a lot easier with the introduction of the Google code scanner API. You can also use the API to integrate a scanner in your existing apps.
Our app delegates the task of scanning the barcode to the Google code scanner API. One advantage of this strategy is its simplicity. One disadvantage is that you can't use it for more complex situations which require a custom UI. In that case, you will need to directly use the ML Kit barcode scanning API.