Scanning QR code using Android's Mobile Vision API
Asked Answered
E

4

18

I followed this tutorial on how to build an Android app that can scan QR codes.

Here's the full code. I added the Google Play services using grade like so compile 'com.google.android.gms:play-services:7.8.0'.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="bitinvent.io.qrscanner" >

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

activity_main.xml

<?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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <SurfaceView
        android:id="@+id/cameraView"
        android:layout_width="640px"
        android:layout_height="480px"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"/>

    <TextView
        android:id="@+id/infoTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/cameraView"
        android:layout_marginLeft="16dp"
        android:text="Nothing to read"
        android:textSize="20sp"/>

</RelativeLayout>

MainActivity.java

package bitinvent.io.qrscanner;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;

import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;

import java.io.IOException;

public class MainActivity extends Activity {

    private SurfaceView cameraView;
    private TextView barcodeInfo;
    private CameraSource cameraSource;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        cameraView = (SurfaceView) findViewById(R.id.cameraView);
        barcodeInfo = (TextView) findViewById(R.id.infoTextView);

        BarcodeDetector detector = new BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.QR_CODE).build();
        cameraSource = new CameraSource.Builder(this, detector).setRequestedPreviewSize(640, 480).build();

        cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    cameraSource.start(cameraView.getHolder());
                } catch (IOException e) {
                    Log.e("CAMERA SOURCE", e.getMessage());
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });

        detector.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() {
                        @Override
                        public void run() {
                            barcodeInfo.setText(barcodes.valueAt(0).displayValue);
                        }
                    });
                }
            }
        });
    }
}

I tested this on a HTC Desire 816 running Android 4.4.2. But it doesn't seem to work. The camera view is active but when pointed at a QR code, it doesn't detect anything. But no errors or crashes occur either.

Am I missing something?

Extend answered 29/10, 2015 at 17:57 Comment(4)
Hi, I know it's a pretty old question but I'm facing the same problem with android 4.4.2. On Android 6 it's working fine, but on this version the qr-code is never getting any result.. you know why?Carrington
@PierGiorgioMisley No, I couldn't find a solution to this issue either. Sorry.Extend
ok thanks you very much, I will tell you something if I find a workaroundCarrington
@PierGiorgioMisley Thank you. Do post an answer if you find anything.Extend
M
7

Finally I got it working in my side. I wanted to share the process and the code that I have right now to implement the QR code scanning in my application. I am not actually answering your question. However, I did not find any good source of help from StackOverflow regarding how can I implement QR code scanning using Google Vision API. I looked into the tutorial that you pointed in your question. However, the tutorial was not very helpful to me either. Hence I am putting down the classes and the steps to implement the QR code scanning in my application.

First of all, you will need some gradle dependencies. So in your build.gradle file, add the following dependencies.

dependencies {
    compile 'com.android.support:design:25.3.1'
    compile 'com.google.android.gms:play-services-vision:10.2.1'
}

Then, you need to have the following five classes in your project. I am adding the classes here. Please import the missing classes if necessary.

  1. CameraSource.java
  2. CameraSourcePreview.java
  3. BarcodeCaptureActivity.java
  4. BarcodeGraphicTracker.java
  5. BarcodeTrackerFactory.java

Now BarcodeCaptureActivity has a layout which you need to put in your layout folder as well.

Here's the barcode_capture.xml layout that you need.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/topLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true"
    android:orientation="vertical">

    <!-- Do not forget to replace with your package name where the class is located -->
    <com.example.yourpackage.camera.CameraSourcePreview
        android:id="@+id/preview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

You will need some strings and an activity entry in manifest for the BarcodeCaptureActivity. Here are the strings that you need to put in your strings.xml.

<!-- QR Code related strings -->
<string name="permission_camera_rationale">Access to the camera is needed for detection</string>
<string name="no_camera_permission">This application cannot run because it does not have the camera permission.  The application will now exit.</string>
<string name="low_storage_error">Face detector dependencies cannot be downloaded due to low device storage</string>
<string name="ok">OK</string>

And the AndroidManifest.xml should have a new entry for the BarcodeCaptureActivity like the following.

<activity
    android:name=".util.scanner.BarcodeCaptureActivity"
    android:theme="@style/Theme.AppCompat" />

Now your setup is done and you are ready to open your camera for scanning a barcode or QR code. Just call the following initiateScan function where necessary.

public static final int RC_BARCODE_CAPTURE = 9001;

public void initiateScan() {
    Intent intent = new Intent(YourActivity.this, BarcodeCaptureActivity.class);
    startActivityForResult(intent, RC_BARCODE_CAPTURE);
}

Please note that, you need to ask for camera permission to the user before you call initiateScan function. On granting the permission of the camera you will call the initiateScan function.

The initiateScan function will open the scanner and then after a successful scan, it will return to the calling Activity or Fragment. So you need to have a onActivityResult function in the calling Activity or Fragment.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == CommonStatusCodes.SUCCESS && requestCode == RC_BARCODE_CAPTURE) {
        if (data == null) return;
        Barcode barcode = data.getParcelableExtra(BarcodeCaptureActivity.BarcodeObject);
        final String scanResult = barcode.displayValue;
        if (scanResult == null) return;

        doSomethingWithTheScanResult(scanResult);
    }
}

Do not forget to add the CAMERA permission in your AndroidManifest.xml file as well.

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

Hope that helps for easier integration of QR code scanner using Google Vision API. I have added a github project for a sample QR code scanner application. Please have a look.

Maund answered 5/4, 2018 at 20:6 Comment(3)
What if I want it to scan QR code only in a square?Dillydally
@Dillydally I think you have to implement the SurfaceView to get your camera opened in the squared box. There's a similar question that might help you - #13951404Maund
No, I mean full camera view but only scan when it's in a square box.Dillydally
A
1

Try move the following line

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

to your activity tag in yout manifest right after <intent-filter/>

so it would look like this

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

Lemme know if it helps

Aggravate answered 8/9, 2017 at 7:11 Comment(0)
M
0

I'm new to Android development but I followed the tutorial using play services 8.1. Worked.

Code is very similar to yours. Only differences are that I have the meta tag under the application level and I removed .setBarcodeFormats(Barcode.QR_CODE) since it limits it specifically to QR type codes.

Also used the app in landscape since portrait wasn't working for me. Even in landscape for QR codes I sometimes had to slowly move the QR code away from the camera until it was able to recognize it.

Medicaid answered 24/11, 2015 at 23:5 Comment(0)
B
0

Did you enabled internet connection in the device? In order to download data via Google Play services; it requires internet connection over the device however you need not to provide any permission.

Burkett answered 29/8, 2017 at 8:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.