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.
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Keshav Gupta
Keshav Gupta is Android Developer in Oodles, he always look forward for new tasks and new things to learn more.