Skip to content

QR Device Engagement

SDK provides user with a complete QR code scanner for scanning device engagement QR codes.


In order to use this feature you will have to consider the following:

  1. Permission Manifest.permissions.CAMERA must be granted by end user.
  2. Instantiate the QRDeviceEngagement class. Then enable the device engagement detection by calling the QRDeviceEngagement#enableDeviceEngagement(ComponentActivity, DeviceEngagementCallback) method in an activity's onCreate method, since it is need to be registered before the activity's Lifecycle.Event.ON_START event.

Launching QR scan & Options

To launch the QR Scanner any of the QRDeviceEngagement#scanQR() or QRDeviceEngagement#scanQR(Options) must be called.

The available Options are:

  • Use the front camera: Options#useFrontCamera(boolean)

Getting the device engagement

When scanning QR code the DeviceEngagement#onEngage(Received<EngagementReceived>) method is called.

In the success scenario, where a valid device engagement QR code is scanned, the Received<EngagementReceived> contains an EngagementReceived object which holds the DeviceEngagement and the Handover, which in this case is a Handover.QR.

When QR code scan fails, then Received<EngagementReceived> argument is Failure instance with one of the following FailureTypes:

  • FailureType#DE_CAMERA_PERMISSION: Manifest.permissions.CAMERA is not granted
  • FailureType#DE_QR_INVALID: The scanned QR is not a valid Device Engagement QR code
  • FailureType#DE_QR_MISSING: The QR scanner didn't scan a QR code
  • FailureType#DE_QR_CANCELED: User canceled the QR scanning, e.g. pressed the back button

Sample code

The following sample Activity demonstrates a typical QRDeviceEngagement usage.


import static;

import android.Manifest.permission;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;

import com.scytales.mvalid.sdk.Received;
import com.scytales.mvalid.sdk.SDKException;
import com.scytales.mvalid.sdk.engagement.DeviceEngagement;
import com.scytales.mvalid.sdk.engagement.DeviceEngagementCallback;
import com.scytales.mvalid.sdk.engagement.EngagementReceived;
import com.scytales.mvalid.sdk.engagement.qr.QRDeviceEngagement;
import com.scytales.mvalid.sdk.session.Handover;

public class MainActivity extends AppCompatActivity
        implements DeviceEngagementCallback {

    private static final String TAG = "MainActivity";

    private final QRDeviceEngagement qrDeviceEngagement = new QRDeviceEngagement();

    private final ActivityResultLauncher<String> requestPermissionLauncher =
            registerForActivityResult(new RequestPermission(), isGranted -> {
                if (isGranted) {

    protected void onCreate(Bundle savedInstanceState) {

        // see more about requesting permissions in

        if (ContextCompat.checkSelfPermission(this, permission.CAMERA) == PERMISSION_GRANTED) {
        } else {

        try {
            qrDeviceEngagement.enableDeviceEngagement(this, this);
        } catch (SDKException e) {
            Log.e(TAG, "onCreate", e);
            // handle failed initialization

    private void enableScanQrBtn() {
        Button scanQrBtn = findViewById(;
        scanQrBtn.setOnClickListener(v -> qrDeviceEngagement.scanQR());

    public void onEngage(@NonNull Received<EngagementReceived> received) {
        Log.d(TAG, received.toString());
                failure -> {
                    Log.e(TAG, failure.toString());
                    FailureType type = failure.getType();
                    // handle failed device engagement
                success -> {
                    Handover handover = success.getHandover();
                    DeviceEngagement deviceEngagement = success.getDeviceEngagement();

                    // ... use handover to determine the device engagement QR/NFC
                    // ... deviceEngagement contains the engagement information to
                    // proceed with data transfer