Hello guy’s, today we gonna look out how to work with QRCode. Recently, I’ve been working on my startup. My startup is based on Wallet App. So, I had to implement QRCode generator and reader on the client side. When creating the app I had faced a lot difficulty to find the right solution. So, I thought it might be good to write a blog about it.

So, let’s see how can we generate and read QRCode in Android app with the custom object. In this example, we’re going to use Zxing library for reading and generating QRCode.

First, add the following dependency in your app level build.gradle file.

// Zxing barcode dependency implementation 'me.dm7.barcodescanner:zxing:1.9.8'

Now add the following permission in Android Manifest file.

<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.hardware.camera" /> <uses-permission android:name="android.hardware.camera.autofocus" />

Now the setup part is done. Let’s see how can we read the QRCode.

Reading QRCode

Add the ZxingScannerView in your activity xml file.

<me.dm7.barcodescanner.zxing.ZXingScannerView android:id="@+id/qrCodeScanner" android:layout_width="match_parent" android:layout_height="match_parent"> </me.dm7.barcodescanner.zxing.ZXingScannerView>

Now get the ZxingScannerView reference in the activity class.

val qrCodeScanner = findViewById<ZxingScannerView>(R.id.qrCodeScanner) setScannerProperties()

setScannerProperites is my custom method. ZxingScannerView needs some basic properties before start scanning. The following shows how to set scanner properties.

/** * Set Qr code scanner basic properties. */ private fun setScannerProperties() { qrCodeScanner.setFormats(listOf(BarcodeFormat.QR_CODE)) qrCodeScanner.setAutoFocus(true) qrCodeScanner.setLaserColor(R.color.colorAccent) qrCodeScanner.setMaskColor(R.color.colorAccent) if (Build.MANUFACTURER.equals(HUAWEI, ignoreCase = true)) qrCodeScanner.setAspectTolerance(0.5f) }

Now we need to start the scanner. It’s a good approach that we start scanner in onResume and stop the scanner in on onPause.

The following shows to start scanner.

override fun onResume() { super.onResume() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), MY_CAMERA_REQUEST_CODE) return } } qrCodeScanner.startCamera() qrCodeScanner.setResultHandler(this) }

You see the setResultHandler is accepting the RequestHandler type interface and bypassing “this” reference our activity needs to implement this interface.

override fun handleResult(p0: Result?) { if (p0 != null) { Toast.makeText(this,p0.text,Toast.LENGTH_LONG).show() } }

Now, this abstract function called every time whenever scanner successfully scanned. The scanned result is in Result type object.

The following shows how to stop scanner in onStop or in the onPause method.

/** * stop the qr code camera scanner when activity is in the onPause state. */ override fun onPause() { super.onPause() qrCodeScanner.stopCamera() }

Generating QRCode

Generating a QR code is very easy. You guys must be remembered that I said, we’re going to generate QRCode with Custom Object. By, custom object means we can store user info like name, email,image_url etc in QRCode. So, in this example, we’re going to store user full name and age in QRCode. So, when we scan the QRCode, we get user info in the Result object.

Now, this is another activity for generating the QR code. Below is code for the xml file.

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorPrimary" tools:context=".GenerateQrCodeActivity"> <android.support.design.widget.TextInputLayout android:id="@+id/fullNameLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginStart="10dp" android:layout_marginTop="15dp" android:theme="@style/TextLabel"> <android.support.v7.widget.AppCompatEditText android:id="@+id/fullNameEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawablePadding="10dp" android:hint="@string/full_name" android:inputType="textCapSentences" android:paddingEnd="8dp" android:paddingStart="8dp" android:textColor="@color/whiteColor" android:textSize="15sp" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:id="@+id/ageLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/fullNameLayout" android:layout_marginEnd="10dp" android:layout_marginStart="10dp" android:layout_marginTop="10dp" android:theme="@style/TextLabel"> <android.support.v7.widget.AppCompatEditText android:id="@+id/ageEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawablePadding="10dp" android:hint="@string/user_age" android:inputType="number" android:paddingEnd="8dp" android:paddingStart="8dp" android:textColor="@color/whiteColor" android:textSize="15sp" /> </android.support.design.widget.TextInputLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/generateQrCodeButton" android:layout_below="@+id/ageLayout" android:layout_marginBottom="5dp" android:layout_marginTop="5dp"> <ImageView android:id="@+id/qrCodeImageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginEnd="25dp" android:layout_marginStart="25dp" android:contentDescription="@null" /> </FrameLayout> <Button android:id="@+id/generateQrCodeButton" style="?android:buttonBarButtonStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@drawable/square_primary_button_drawable" android:text="@string/generate_qr_code" android:textColor="@color/whiteColor" android:textStyle="bold" /> </RelativeLayout>

Now in this xml, we have one EditText for the full name and one for user age. We have an ImageView where we show the QR code and one Button for generating QR code.

I’m gonna show you quickly how to generate QR code except for the prep work.

The following shows how to generate QR code.

generateQrCodeButton.setOnClickListener { if (checkEditText()) { val user = UserObject(fullName = fullNameEditText.text.toString(), age = Integer.parseInt(ageEditText.text.toString())) val serializeString = Gson().toJson(user) val bitmap = QRCodeHelper .newInstance(this) .setContent(encryptedString) .setErrorCorrectionLevel(ErrorCorrectionLevel.Q) .setMargin(2) .getQRCOde() qrCodeImageView.setImageBitmap(bitmap) } }

You see in click listener we’re creating a User object for QR code. We can only create QR code with String. So, we have to serialize the User object into a string with Gson. After that, we need to set QR code setting for generating the code. The QRCodeHelper is my custom class for the generating QR code.

Note: You see we’re serializing the user object when generating the code. So, we’ve to deserialize the string into User object when the scanner successfully scanned the QR code. One more important thing to say here please do not create a huge object for creating QR code. If you create a huge object your scanner needs more time to scan the code.

Below is the QRCodeHelper class.

public class QRCodeHelper { private static QRCodeHelper qrCodeHelper = null; private ErrorCorrectionLevel mErrorCorrectionLevel; private int mMargin; private String mContent; private int mWidth, mHeight; /** * private constructor of this class only access by stying in this class. */ private QRCodeHelper(Context context) { mHeight = (int) (context.getResources().getDisplayMetrics().heightPixels / 2.4); mWidth = (int) (context.getResources().getDisplayMetrics().widthPixels / 1.3); Log.e("Dimension = %s", mHeight + ""); Log.e("Dimension = %s", mWidth + ""); } /** * This method is for singleton instance od this class. * * @return the QrCode instance. */ public static QRCodeHelper newInstance(Context context) { if (qrCodeHelper == null) { qrCodeHelper = new QRCodeHelper(context); } return qrCodeHelper; } /** * This method is called generate function who generate the qrcode and return it. * * @return qrcode image with encrypted user in it. */ public Bitmap getQRCOde() { return generate(); } /** * Simply setting the correctionLevel to qrcode. * * @param level ErrorCorrectionLevel for Qrcode. * @return the instance of QrCode helper class for to use remaining function in class. */ public QRCodeHelper setErrorCorrectionLevel(ErrorCorrectionLevel level) { mErrorCorrectionLevel = level; return this; } /** * Simply setting the encrypted to qrcode. * * @param content encrypted content for to store in qrcode. * @return the instance of QrCode helper class for to use remaining function in class. */ public QRCodeHelper setContent(String content) { mContent = content; return this; } /** * Simply setting the width and height for qrcode. * * @param width for qrcode it needs to greater than 1. * @param height for qrcode it needs to greater than 1. * @return the instance of QrCode helper class for to use remaining function in class. */ public QRCodeHelper setWidthAndHeight(@IntRange(from = 1) int width, @IntRange(from = 1) int height) { mWidth = width; mHeight = height; return this; } /** * Simply setting the margin for qrcode. * * @param margin for qrcode spaces. * @return the instance of QrCode helper class for to use remaining function in class. */ public QRCodeHelper setMargin(@IntRange(from = 0) int margin) { mMargin = margin; return this; } /** * Generate the qrcode with giving the properties. * * @return the qrcode image. */ private Bitmap generate() { Map<EncodeHintType, Object> hintsMap = new HashMap<>(); hintsMap.put(EncodeHintType.CHARACTER_SET, "utf-8"); hintsMap.put(EncodeHintType.ERROR_CORRECTION, mErrorCorrectionLevel); hintsMap.put(EncodeHintType.MARGIN, mMargin); try { BitMatrix bitMatrix = new QRCodeWriter().encode(mContent, BarcodeFormat.QR_CODE, mWidth, mHeight, hintsMap); int[] pixels = new int[mWidth * mHeight]; for (int i = 0; i < mHeight; i++) { for (int j = 0; j < mWidth; j++) { if (bitMatrix.get(j, i)) { pixels[i * mWidth + j] = 0xFFFFFFFF; } else { pixels[i * mWidth + j] = 0x282946; } } } return Bitmap.createBitmap(pixels, mWidth, mHeight, Bitmap.Config.ARGB_8888); } catch (WriterException e) { e.printStackTrace(); } return null; } }

That’s it guy’s, this is my demonstration about generating and reading QR code with the custom object. If you guy’s want to see the code of the example, that I’ve shown you in the above see it on GitHub.

I hope you guys learn how can we generate and read QR code. If you have any queries please do comment below.

Thank you for being here and keep reading…