Android QR Code Scanner / Android Barcode Scanner Example
QR code and Barcode technology are being more famous this day. Almost every product has a barcode on it. QR code and Barcode can contain any information like name, ids. These QR / Barcodes are not humanly readable it can be read by using QR Code Scanner and Bar Code Scanner. So in this post, we learn to build Android QR Code Scanner and Android Barcode Scanner.
DOWNLOAD PROJECT
DEMO
What is QR Code?
QR code is a bundle of Black and White squares. Information like URLs, Personal information etc. are stored in QR codes. Smartphones or Camera can read this encoded information. For Android smartphone users there are plenty of apps on Playstore.
What is Barcode?
Barcode is Bundle of vertical lines with a variety of widths. Contains products full information like serial number, product number etc. Smartphones or Barcode Scanners can read this encoded information.
Building Android QR Code Scanner / Android Barcode Scanner
Create new Android studio project File -> New Project or use existing. To decode information from barcodes and QR codes we need Zxing library.
Adding Zxing Library into project
1. Open build.gradle(module app) file and modify according to following snippets.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
apply plugin: 'com.android.application' android { compileSdkVersion 26 defaultConfig { applicationId "com.loopwiki.qrsacnner" minSdkVersion 15 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support:design:26.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' /*Add QR Zxing Library Here */ implementation 'com.journeyapps:zxing-android-embedded:3.5.0' } |
Creating Custom Scanner Activity
2. Create new layout -> custom_scanner.xml. This layout will contain BarcodeView and ViewfinderView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <!--Bar code Scanner window--> <com.journeyapps.barcodescanner.BarcodeView android:id="@+id/zxing_barcode_surface" android:layout_width="match_parent" android:layout_height="match_parent" app:zxing_framing_rect_height="200dp" app:zxing_framing_rect_width="250dp" /> <!--Full Camera Window with viewfinder--> <com.journeyapps.barcodescanner.ViewfinderView android:id="@+id/zxing_viewfinder_view" android:layout_width="match_parent" android:layout_height="match_parent" app:zxing_possible_result_points="@color/colorPrimary" app:zxing_result_view="@color/colorAccent" app:zxing_viewfinder_laser="@color/colorPrimaryDark" app:zxing_viewfinder_mask="@color/transparent_blue" /> <!--Help Text--> <TextView android:id="@+id/zxing_status_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top|center_horizontal" android:gravity="center" android:text="@string/message" android:textAppearance="@style/TextAppearance.AppCompat.Large" android:textColor="@color/zxing_status_text" /> </merge> |
Breaking custom_scanner.xml
BarcodeView is a small window from ViewfinderView. This is the area in which we will move QR code or Barcode to scan.
ViewfinderView this is a view where camera visuals are shown.
3. Create new layout -> content_scanner.xml. This layout will DecoratedBarcodeView and flashlight button. Add Following snippets to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.loopwiki.qrsacnner.ScannerActivity" tools:showIn="@layout/activity_scanner"> <!-- set custom layout for scanner--> <com.journeyapps.barcodescanner.DecoratedBarcodeView android:id="@+id/zxing_barcode_scanner" android:layout_width="match_parent" android:layout_height="match_parent" app:zxing_scanner_layout="@layout/custom_scanner" /> <!-- FlashLight Button--> <Button android:id="@+id/switch_flashlight" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:text="@string/turn_off_flashlight" /> </RelativeLayout> |
4. create new layout ->activity_scanner.xml will contain our toolbar and content_scanner.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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="com.loopwiki.qrsacnner.ScannerActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_scanner" /> </android.support.design.widget.CoordinatorLayout> |
5. Create new class Package Name -> ScannerActivity.java. In this class, we can put our programmable logic as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
package com.loopwiki.qrsacnner; import android.content.pm.PackageManager; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.KeyEvent; import android.view.View; import android.widget.Button; import com.journeyapps.barcodescanner.CaptureManager; import com.journeyapps.barcodescanner.DecoratedBarcodeView; public class ScannerActivity extends AppCompatActivity implements DecoratedBarcodeView.TorchListener { private CaptureManager capture; private DecoratedBarcodeView barcodeScannerView; private Button switchFlashlightButton; private boolean isFlashLightOn = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scanner); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); //Initialize barcode scanner view barcodeScannerView = findViewById(R.id.zxing_barcode_scanner); //set torch listener barcodeScannerView.setTorchListener(this); //switch flashlight button switchFlashlightButton = (Button) findViewById(R.id.switch_flashlight); // if the device does not have flashlight in its camera, // then remove the switch flashlight button... if (!hasFlash()) { switchFlashlightButton.setVisibility(View.GONE); } else { switchFlashlightButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { switchFlashlight(); } }); } //start capture capture = new CaptureManager(this, barcodeScannerView); capture.initializeFromIntent(getIntent(), savedInstanceState); capture.decode(); } /** * Check if the device's camera has a Flashlight. * * @return true if there is Flashlight, otherwise false. */ private boolean hasFlash() { return getApplicationContext().getPackageManager() .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH); } public void switchFlashlight() { if (isFlashLightOn) { barcodeScannerView.setTorchOff(); isFlashLightOn = false; } else { barcodeScannerView.setTorchOn(); isFlashLightOn = true; } } @Override public void onTorchOn() { switchFlashlightButton.setText(R.string.turn_off_flashlight); } @Override public void onTorchOff() { switchFlashlightButton.setText(R.string.turn_on_flashlight); } @Override protected void onResume() { super.onResume(); capture.onResume(); } @Override protected void onPause() { super.onPause(); capture.onPause(); } @Override protected void onDestroy() { super.onDestroy(); capture.onDestroy(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); capture.onSaveInstanceState(outState); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return barcodeScannerView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); } } |
Breaking ScannerActivity
Following piece of code is used to initialize QR / Barcode Scanner.
capture = new CaptureManager(this, barcodeScannerView); capture.initializeFromIntent(getIntent(), savedInstanceState); capture.decode();
Now if users smart phone has flashlight feature then we will initilize flashlight button. This button will turn flashlight according to user’s choice.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
//switch flashlight button switchFlashlightButton = (Button) findViewById(R.id.switch_flashlight); // if the device does not have flashlight in its camera, // then remove the switch flashlight button... if (!hasFlash()) { switchFlashlightButton.setVisibility(View.GONE); } else { switchFlashlightButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { switchFlashlight(); } }); } /** * Check if the device's camera has a Flashlight. * * @return true if there is Flashlight, otherwise false. */ private boolean hasFlash() { return getApplicationContext().getPackageManager() .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH); } public void switchFlashlight() { if (isFlashLightOn) { barcodeScannerView.setTorchOff(); isFlashLightOn = false; } else { barcodeScannerView.setTorchOn(); isFlashLightOn = true; } } |
Creating MainActvity
6. Create new layout -> content_main.xml. This layout will contain scan button which will launch QR/Barcode scan.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.loopwiki.qrsacnner.MainActivity" tools:showIn="@layout/activity_main"> <Button android:id="@+id/buttonScan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Scan" /> </RelativeLayout> |
7. Create new layout -> activity_main.xml contain toolbar and content_main.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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="com.loopwiki.qrsacnner.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> </android.support.design.widget.CoordinatorLayout> |
8. Create new class Package name ->MainActivity.java. This is activity class. In this class, we will launch Scanning by clicking scan button.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
package com.loopwiki.qrsacnner; import android.content.ClipData; import android.content.ClipboardManager; import android.content.DialogInterface; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Button; import android.widget.Toast; import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); //Scan Button Button buttonBarCodeScan = findViewById(R.id.buttonScan); buttonBarCodeScan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //initiate scan with our custom scan activity new IntentIntegrator(MainActivity.this).setCaptureActivity(ScannerActivity.class).initiateScan(); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //We will get scan results here IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); //check for null if (result != null) { if (result.getContents() == null) { Toast.makeText(this, "Scan Cancelled", Toast.LENGTH_LONG).show(); } else { //show dialogue with result showResultDialogue(result.getContents()); } } else { // This is important, otherwise the result will not be passed to the fragment super.onActivityResult(requestCode, resultCode, data); } } //method to construct dialogue with scan results public void showResultDialogue(final String result) { AlertDialog.Builder builder; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { builder = new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert); } else { builder = new AlertDialog.Builder(this); } builder.setTitle("Scan Result") .setMessage("Scanned result is " + result) .setPositiveButton("Copy result", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // continue with delete ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("Scan Result", result); clipboard.setPrimaryClip(clip); Toast.makeText(MainActivity.this, "Result copied to clipboard", Toast.LENGTH_SHORT).show(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // do nothing dialog.dismiss(); } }) .show(); } } |
Breaking MainActivity
Following snippets will launch our Scanner Activity for results. Seems after launching ScannerActvity this activity will wait for the result of the scan.
1 2 |
//initiate scan with our custom scan activity new IntentIntegrator(MainActivity.this).setCaptureActivity(ScannerActivity.class).initiateScan(); |
There are two cases here user will scan any QR/barcode and a user will cancel the scan. Manage both results in onActivityResult() method. Show Result to the user if the user scans QR code or Barcode.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //We will get scan results here IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); //check for null if (result != null) { if (result.getContents() == null) { Toast.makeText(this, "Scan Cancelled", Toast.LENGTH_LONG).show(); } else { //show dialogue with result showResultDialogue(result.getContents()); } } else { // This is important, otherwise the result will not be passed to the fragment super.onActivityResult(requestCode, resultCode, data); } } |
To show the result to the user we will build a dialogue. This dialogue is constructed by using showResultDialogue() method. This dialogue will display the result with copy and cancel button.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//method to construct dialogue with scan results public void showResultDialogue(final String result) { AlertDialog.Builder builder; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { builder = new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert); } else { builder = new AlertDialog.Builder(this); } builder.setTitle("Scan Result") .setMessage("Scanned result is " + result) .setPositiveButton("Copy result", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // continue with delete ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("Scan Result", result); clipboard.setPrimaryClip(clip); Toast.makeText(MainActivity.this, "Result copied to clipboard", Toast.LENGTH_SHORT).show(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // do nothing dialog.dismiss(); } }) .show(); } |
9. Download Values folder from here. This folder contains necessary styles, colors, and strings. Copy and paste this styles, colors, and strings to your project.
10. Modify manifest.xml as follows. Remember to add camera permission.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.loopwiki.qrsacnner"> <uses-permission android:name="android.permission.CAMERA" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".ScannerActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"> </activity> <activity android:name=".MainActivity" android:label="@string/title_activity_main" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
Done now run the application.
If you still have any queries, please post them in the comments section below, I will be happy to help you. If you have any other questions in mind then make sure to visit our ask section.
Working Perfectly.Great job. Thank a lot. You saved my day.
Welcome Mate ! 🙂
how to switch back camera to front camera
Just invoke by Intent and set extra SCAN_CAMERA_ID to the ID of the camera you want — usually 1 for the front one.
Example
Good job sir. i was wondering how to open a url automatically if scan result is a website address