Create Qr scanner for android using mobile vision api by google

Posted By : Keshav Gupta | 29-Jul-2018

Steps to Configure In android

Step1: Install google play services dependency in the application. Add dependency in app/build.gradle.

implementation 'com.google.android.gms:play-services:10.2.0'

Step2: Create a layout having component SurfaceView to open camera and toolbar showing the label for the scan and a view floating over the surface view that represents scan area to be scanned by this.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    >

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/bggradientdrawable">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <ImageView
                android:id="@+id/image_back_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_centerVertical="true"
                android:padding="@dimen/margin_5"
                android:src="@drawable/back" />
            <TextView
                android:id="@+id/label_toolbar"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@+id/image_back_icon"
                android:layout_centerVertical="true"
                android:fontFamily="@font/lato_regular"
                android:layout_marginLeft="@dimen/margin_10"
                android:text="@string/scan"
                android:textColor="@color/colorlogintop"
                android:textSize="@dimen/textsize_18sp" />


        </RelativeLayout>

    </android.support.v7.widget.Toolbar>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/code_info"
        android:layout_below="@+id/toolbar">

        <SurfaceView
            android:id="@+id/camera_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <RelativeLayout
            android:id="@+id/rl_qrlabel"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:visibility="gone"
            >
            <TextView
                android:id="@+id/text_scanlabel"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/scanatqr"
                android:fontFamily="@font/lato_regular"
                android:textColor="@color/colorlogintop"
                android:gravity="center"
                />

            <ImageView
                android:layout_width="@dimen/margin_200"
                android:layout_height="@dimen/margin_200"
                android:layout_below="@+id/text_scanlabel"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="16dp"
                android:src="@drawable/qrcode"
                android:id="@+id/imageView4" />
        </RelativeLayout>
    </FrameLayout>

    <TextView
        android:id="@+id/code_info"
        android:layout_width="match_parent"
        android:layout_height="@dimen/margin_40"
        android:visibility="gone"
        android:layout_alignParentBottom="true"
        android:text="" />
</RelativeLayout>

Step3:In AndroidManifest.xml file,create a metadata in <application> </application> tag showing  mobile vision dependencies for barcode.

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

Step4: Further add user permission for camera and Read_External_Storage under <Manifest> </Manifest> tag.Camera permission is required for accessing camera hardware and to customize camera on another view.

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

Note: For Android Version 6.0 and above you need to define user permission model for taking permission at runtime.?

Step5: Create an Activity class named as CameraPreviewScreen that will represent behavior action for SurfaceView and a CameraSource and BarcodeDetector.We will create BarcodeDetector object and set Barcode format to Qr as we are going to create Qr scanner and build it.

Step6: Next we will create CameraSource class object and set Camera attributes like as autofocus enabled to true, preview size and Camera source builder attribute to barcode detector.

Step7: Next we will set SurfaceView callback. In overridden methods onSurfaceCreated() camera source will start and onSurfaceDestroyed() camera source will be stopped.

Step8: Now we will set processor on the barcode detector. In overridden method, onReceiveDetections(), we will get scanned value and I am showing an AlertDialog showing scanned value and ok and cancel button. If you wanted to go with the scanned value. Press ok otherwise cancel to further rescan the Qr.

Step9: Code will be like

public class CameraPreviewScreen extends AppCompatActivity {

    @BindView(R.id.rl_qrlabel) RelativeLayout rLayout_QrcodeWindow;
    @BindView(R.id.image_back_icon) ImageView iv_backbtn;
    @BindView(R.id.camera_view) SurfaceView cameraView;
    @BindView(R.id.code_info) TextView barcodeInfo;
    @BindView(R.id.text_scanlabel) TextView tv_label_qr;
    @BindView(R.id.label_toolbar) TextView tv_toolbartext;
    private BarcodeDetector barcodeDetector;
    private CameraSource cameraSource;
    private AppCompatActivity activity;
    private AlertDialog dialog;
    private String scannedMesg;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.qrcamerascreen);
        getSupportActionBar().hide();
        ButterKnife.bind(this);
        activity=CameraPreviewScreen.this;
                showViewBarcode();
    }

  private void showViewBarcode()
  {

      if(barcodeDetector==null)
      {
          barcodeDetector =
                  new BarcodeDetector.Builder(this)
                          .setBarcodeFormats(Barcode.QR_CODE)
                          .build();
      }
      int dimenswidth=getResources().getDimensionPixelSize(R.dimen.margin_200);
      cameraSource = new CameraSource
              .Builder(this, barcodeDetector)
              .setAutoFocusEnabled(true).setRequestedPreviewSize(dimenswidth, dimenswidth)
              .build();


      cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
          @Override
          public void surfaceCreated(SurfaceHolder holder) {
              try {
                  cameraSource.start(cameraView.getHolder());
                  rLayout_QrcodeWindow.setVisibility(View.VISIBLE);
              } catch (IOException ie) {
                  Logger.LogError("CAMERA SOURCE", ie.getMessage());
              }catch (SecurityException ie) {
                  Logger.LogError("CAMERA SOURCE", ie.getMessage());
              }
          }

          @Override
          public void surfaceChanged(SurfaceHolder surfaceholder, int sformat, int swidth, int sheight) {

          }

          @Override
          public void surfaceDestroyed(SurfaceHolder holder) {
              cameraSource.stop();
              rLayout_QrcodeWindow.setVisibility(View.GONE);
          }
      });


      barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
          @Override
          public void release() {

          }

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

              if (barcodes.size() != 0) {
                  barcodeInfo.post(new Runnable() {    // Use the post method of the TextView
                      public void run() {

                          Logger.LogError("Code",barcodes.valueAt(0).displayValue);

                          showMessageDialog(barcodes.valueAt(0).displayValue);
                          if(barcodeDetector!=null)
                          {
                              barcodeDetector.release();
                          }


                      }
                  });
              }
          }
      });
  }


    @OnClick(R.id.image_back_icon)
    public void onClickBack() {
        finish();
    }


    private void showMessageDialog(final String mesg)
    {

        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setTitle(R.string.QRCode);
        String s=mesg;
        if(s.contains(":")){
            s=s.substring(s.indexOf(":")+1);
        }
        if(s.contains("?")) {
            s=s.substring(0,s.indexOf("?"));
        }

        scannedMesg=s;
        builder.setMessage(s);
        builder.setCancelable(false);
        String positiveText = getString(android.R.string.ok);
        builder.setPositiveButton(positiveText,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                       dialog.dismiss();
                        // code to do when scanning is done properly
                           invokeSendCoinsWithWallet(scannedMesg);
                           finish();
                    }
                });
        String negativeText = getString(android.R.string.cancel);
        builder.setNegativeButton(negativeText,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        if(cameraSource!=null)
                        {
                            if(barcodeDetector !=null)
                            {
                                barcodeDetector.release();
                            }
                           // cameraSource.release();
                            cameraSource.stop();
                        }
                        Intent intent=new Intent(CameraPreviewScreen.this,CameraPreviewScreen.class);
                        startActivity(intent);
                        finish();

                    }
                });


        dialog = builder.create();
        // display dialog
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        if(!dialog.isShowing())
        {
            dialog.show();
        }
    }

    private void invokeSendCoinsWithWallet(String  walletAddress){
        Intent intent=new Intent();
        intent.setAction(IntentKeys.INTENT_KEY_QR_ACTION);
        intent.putExtra(IntentKeys.INTENT_KEY_QR_SCANNED,walletAddress);
        sendBroadcast(intent);
    }
}

That's all we have to do for QR scanning.

Request for Proposal

Recaptcha is required.

Sending message..