18

I found a tutorial on how to scan a barcode. But in my application I have to scan a QR code. How can I a scan QR code in Android?

Dan Dascalescu
  • 110,650
  • 40
  • 276
  • 363
Sunil Kumar Sahoo
  • 49,865
  • 50
  • 172
  • 240

7 Answers7

16
try {
    Intent intent = new Intent("com.google.zxing.client.android.SCAN");
    intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); // "PRODUCT_MODE for bar codes

    startActivityForResult(intent, 0);
} catch (Exception e) {    
    Uri marketUri = Uri.parse("market://details?id=com.google.zxing.client.android");
    Intent marketIntent = new Intent(Intent.ACTION_VIEW,marketUri);
    startActivity(marketIntent);
}

and in onActivityResult():

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 0) {
        if (resultCode == RESULT_OK) {
            String contents = data.getStringExtra("SCAN_RESULT");
        }
        if(resultCode == RESULT_CANCELLED){
            //handle cancel
        }
    }
}
Pratik
  • 30,114
  • 17
  • 82
  • 154
Seshu Vinay
  • 12,984
  • 8
  • 56
  • 106
15

2016 update

The current recommendation is to use the Android Barcode API, which works locally (offline), without requiring a server roundtrip:

The Barcode API detects barcodes in real-time, on device, in any orientation. It can also detect multiple barcodes at once.

It reads the following barcode formats:

  • 1D barcodes: EAN-13, EAN-8, UPC-A, UPC-E, Code-39, Code-93, Code-128, ITF, Codabar
  • 2D barcodes: QR Code, Data Matrix, PDF-417, AZTEC

It automatically parses QR Codes, Data Matrix, PDF-417, and Aztec values, for the following supported formats:

  • URL
  • Contact information (VCARD, etc.)
  • Calendar event
  • Email
  • Phone
  • SMS
  • ISBN
  • WiFi
  • Geo-location (latitude and longitude)
  • AAMVA driver license/ID

Check out the codelab - Barcode Detection with the Mobile Vision API.

Roshana Pitigala
  • 7,058
  • 8
  • 38
  • 66
Dan Dascalescu
  • 110,650
  • 40
  • 276
  • 363
11

You can scan QR code easily with zxing add the following dependencies in your gradle

compile 'com.journeyapps:zxing-android-embedded:3.1.0@aar'
compile 'com.google.zxing:core:3.2.0'

Then in your Activity or on Fragment

   IntentIntegrator scanIntegrator = new IntentIntegrator(context);
                scanIntegrator.setPrompt("Scan");
                scanIntegrator.setBeepEnabled(true);
                //The following line if you want QR code
                scanIntegrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES);
                scanIntegrator.setCaptureActivity(CaptureActivityAnyOrientation.class);
                scanIntegrator.setOrientationLocked(true);
                scanIntegrator.setBarcodeImageEnabled(true);
                scanIntegrator.initiateScan();

And then capture the result in onActivityResult

   @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
        if (scanningResult != null) {
            if (scanningResult.getContents() != null) {
                scanContent = scanningResult.getContents().toString();
                scanFormat = scanningResult.getFormatName().toString();
            }

            Toast.makeText(this,scanContent+"   type:"+scanFormat,Toast.LENGTH_SHORT).show();

        }else{
            Toast.makeText(this,"Nothing scanned",Toast.LENGTH_SHORT).show();
        }
    }

Take a look at this sample project , hope it helps you .

Mithun Sarker Shuvro
  • 3,479
  • 6
  • 28
  • 54
7

One way is using the AppCompatActivity and ZXingScannerView.ResultHandler interface.

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;;

import com.android.volley.VolleyError;
import com.example.team.merchant.functional.Request;
import com.example.team.merchant.functional.ResponseListener;
import com.google.zxing.Result;

import me.dm7.barcodescanner.zxing.ZXingScannerView;

/**
 * Created by Prakhar on 5/16/2016.
 */
public class MerchantScannerActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler {
    private ZXingScannerView mScannerView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        RelativeLayout relativeLayout = new RelativeLayout(this);

        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(60, 60);
        params.setMargins(0, 50, 50, 0);
        params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);


        Button switchCamera = new Button(this); //declare a button in layout for camera change option
        switchCamera.setLayoutParams(params);
        switchCamera.setBackgroundResource(R.drawable.switch_camera);
        relativeLayout.addView(switchCamera);
        final int i = getFrontCameraId();
        if (i == -1) {
            switchCamera.setVisibility(View.GONE);
        }


        mScannerView = new ZXingScannerView(this);   // Programmatically initialize the scanner view
        relativeLayout.addView(mScannerView);

        setContentView(relativeLayout);
        final int[] id = {0};
        switchCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mScannerView.stopCamera();
                if (id[0] % 2 == 0) {
                    mScannerView.startCamera(i);
                } else {
                    mScannerView.startCamera();
                }
                id[0]++;
            }
        });

        mScannerView.setResultHandler(this);// Register ourselves as a handler for scan results.

        mScannerView.startCamera();         // Start camera


    }

    @SuppressLint("NewApi")
    int getFrontCameraId() {
        if (Build.VERSION.SDK_INT < 22) {
            Camera.CameraInfo ci = new Camera.CameraInfo();
            for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
                Camera.getCameraInfo(i, ci);
                if (ci.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) return i;
            }
        } else {
            try {
                CameraManager cManager = (CameraManager) getApplicationContext()
                        .getSystemService(Context.CAMERA_SERVICE);
                String[] cameraId = cManager.getCameraIdList();
                for (int j = 0; j < cameraId.length; j++) {
                    CameraCharacteristics characteristics = cManager.getCameraCharacteristics(cameraId[j]);
                    int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
                    if (cOrientation == CameraCharacteristics.LENS_FACING_FRONT)
                        return Integer.parseInt(cameraId[j]);
                }
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
        return -1; // No front-facing camera found
    }

    @Override
    public void onPause() {
        super.onPause();
        mScannerView.stopCamera();           // Stop camera on pause
    }

    @Override
    public void handleResult(Result rawResult) {
       // rawResult.getText()
       // handle your result here
       // handle exceptions here
    }
}

Other can be used in fragments accordingly.

import android.Manifest;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.zxing.ResultPoint;
import com.journeyapps.barcodescanner.BarcodeCallback;
import com.journeyapps.barcodescanner.BarcodeResult;
import com.journeyapps.barcodescanner.CompoundBarcodeView;


/**
 * Created by Prakhar on 3/8/2016.
 */
public class PayWithQrCodeScannerFragment extends Fragment {

    private static final int PERMISSION_REQUEST_CAMERA = 23;
    public static CompoundBarcodeView barcodeScannerView;
    public static BarcodeCallback callback;



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.paywithqrcodescannerfragment, container, false);

        barcodeScannerView = (CompoundBarcodeView) view.findViewById(R.id.zxing_barcode_scanner);


        callback = new BarcodeCallback() {
            @Override
            public void barcodeResult(BarcodeResult result) {
                    // handle result and exceptions here
            }
        return view;
    }

    /**
     * Check if the device's camera has a Flashlight.
     *
     * @return true if there is Flashlight, otherwise false.
     */
    private boolean hasFlash() {
        return getActivity().getApplicationContext().getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
    }


    @Override
    public void onResume() {
        super.onResume();
        if (android.os.Build.VERSION.SDK_INT < 23) {
            barcodeScannerView.resume();
        }
    }


    @Override
    public void onPause() {
        super.onPause();
        if (android.os.Build.VERSION.SDK_INT < 23) {
            barcodeScannerView.pause();
        }
    }

}

Use below written in layout XML file to placeholder the scanner

<com.journeyapps.barcodescanner.CompoundBarcodeView
            android:id="@+id/zxing_barcode_scanner"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:zxing_preview_scaling_strategy="centerCrop"
            app:zxing_use_texture_view="false" />

Build.gradle

compile 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
compile 'com.google.zxing:core:3.2.1'
Prakhar1001
  • 1,093
  • 10
  • 21
3

My way is to use barcodescanner. I uses zxing for scanning bar codes and QR codes. The version 1.9 of the library utilises zxing v3.2.1. It's a wrapper for zxing so the usage is simplier.

In order to do this:

  1. Add dependency to gradle

    compile 'me.dm7.barcodescanner:zxing:1.9'
    
  2. Add camera permission to manifest

    <uses-permission android:name="android.permission.CAMERA"/>
    
  3. Create activity, that will handle scanning

    Manifest:

    <activity
        android:name=".view.component.ScannerActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:theme="@style/AppThemeTransparent"/>
    

    styles.xml:

    <style name="AppThemeTransparent" parent="@style/Theme.AppCompat.Light">
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="android:windowFullscreen">true</item>
        <item name="android:windowContentOverlay">@null</item>
    </style>
    

    Create scanner activity:

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.WindowManager;
    
    import com.google.zxing.BarcodeFormat;
    import com.google.zxing.Result;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    
    import me.dm7.barcodescanner.zxing.ZXingScannerView;
    
    public class ScannerActivity extends Activity implements ZXingScannerView.ResultHandler {
    
        public static final String EXCLUDED_FORMAT = "ExcludedFormat";
        private static final String TAG = ScannerActivity.class.getSimpleName();
        private ZXingScannerView mScannerView;
    
        @Override
        public void onCreate(Bundle state) {
            setStatusBarTranslucent(true);
            super.onCreate(state);
            mScannerView = new ZXingScannerView(this);
            setContentView(mScannerView);
        }
    
        protected void setStatusBarTranslucent(boolean makeTranslucent) {
            if (makeTranslucent) {
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            } else {
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            }
        }
    
        @Override
        public void onResume() {
            super.onResume();
            mScannerView.setResultHandler(this);
            mScannerView.startCamera();
        }
    
        @Override
        public void onPause() {
            super.onPause();
            mScannerView.stopCamera();
        }
    
        @Override
        public void handleResult(Result rawResult) {
            String result = rawResult.getText();
            BarcodeFormat format = rawResult.getBarcodeFormat();
    
            Log.v(TAG, "Scanned code: " + rawResult.getText());
            Log.v(TAG, "Scanend code type: " + rawResult.getBarcodeFormat().toString());
    
            //Return error
            if (result == null) {
                setResult(RESULT_CANCELED, returnErrorCode(result, format));
                finish();
            }
    
            if (result.isEmpty()) {
                setResult(RESULT_CANCELED, returnErrorCode(result, format));
                finish();
            }
    
            //Return correct code
            setResult(RESULT_OK, returnCorrectCode(result, format));
            finish();
        }
    
        private Intent returnErrorCode(String result, BarcodeFormat format) {
            Intent returnIntent = new Intent();
            returnIntent.putExtra(ScannerConstants.ERROR_INFO, getResources().getString(R.string.scanner_error_message));
            return returnIntent;
        }
    
        private Intent returnCorrectCode(String result, BarcodeFormat format) {
            Intent returnIntent = new Intent();
            returnIntent.putExtra(ScannerConstants.SCAN_RESULT, result);
    
            if (format.equals(BarcodeFormat.QR_CODE)) {
                returnIntent.putExtra(ScannerConstants.SCAN_RESULT_TYPE, ScannerConstants.QR_SCAN);
            } else {
                returnIntent.putExtra(ScannerConstants.SCAN_RESULT_TYPE, ScannerConstants.BAR_SCAN);
            }
    
            return returnIntent;
        }
    
        public void excludeFormats(BarcodeFormat item) {
            Collection<BarcodeFormat> defaultFormats = mScannerView.getFormats();
            List<BarcodeFormat> formats = new ArrayList<>();
            for (BarcodeFormat format : defaultFormats) {
                if (!format.equals(item)) {
                    formats.add(format);
                }
            }
            mScannerView.setFormats(formats);
        }
    
        public interface ScannerConstants {
            public static final String SCAN_MODES = "SCAN_MODES";
            public static final String SCAN_RESULT = "SCAN_RESULT";
            public static final String SCAN_RESULT_TYPE = "SCAN_RESULT_TYPE";
            public static final String ERROR_INFO = "ERROR_INFO";
            public static final int BAR_SCAN = 0;
            public static final int QR_SCAN = 1;
        }
    }
    

    Just be sure, that on API 23+ devices a permission for camera usage is granted for the application.

    Open the Activity just like the normal one with result expectation:

    Intent intent = new Intent(AddEquipmentActivity.this, ScannerActivity.class);
    startActivityForResult(intent, SCAN_SERIAL_REQUEST);
    
R. Zagórski
  • 18,351
  • 5
  • 59
  • 86
2

Here is the function that scans the QR Code.

public void scanQR(View v)
{
    try
    {
        Intent intent = new Intent(ACTION_SCAN);
        intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
        startActivityForResult(intent, 0);
    }
    catch (ActivityNotFoundException anfe)
    {
        showDialog(ActivityUserDetails.this, "No Scanner Found",
                "Download a scanner code activity?", "Yes", "No").show();
    }
}

In the above code snippet, I have invoked showDialog() method from catch block, that will show an AlertDialog for asking to install "Barcode Scanner" app from Google Play. Given below is the code for showDialog method.

private static AlertDialog showDialog(final Activity act,
                                      CharSequence title, CharSequence message, CharSequence buttonYes,
                                      CharSequence buttonNo)
{
    AlertDialog.Builder downloadDialog = new AlertDialog.Builder(act);
    downloadDialog.setTitle(title);
    downloadDialog.setMessage(message);
    downloadDialog.setPositiveButton(buttonYes,
            new DialogInterface.OnClickListener()
            {
                public void onClick(DialogInterface dialogInterface, int i)
                {
                    Uri uri = Uri.parse("market://search?q=pname:"
                            + "com.google.zxing.client.android");
                    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                    try
                    {
                        act.startActivity(intent);
                    }
                    catch (ActivityNotFoundException anfe)
                    {

                    }
                }
            });
            downloadDialog.setNegativeButton(buttonNo,
            new DialogInterface.OnClickListener()
            {
                public void onClick(DialogInterface dialogInterface, int i)
                {
                }
            });
            return downloadDialog.show();
}

I have used this function on Button click event. Therefore the code for Button is given below (xml file).

                    <Button
                    android:id="@+id/button_wr_scan"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="5dp"
                    android:background="@drawable/button_shadow"
                    android:onClick="scanQR"
                    android:paddingRight="4dp"
                    android:paddingTop="4dp"
                    android:text="ScanQR" />

NOTE: The prerequisite for using this function is that you must have pre installed "Barcode Scanner" app in your device.

Hope it helps.

Thanks :)

Swanand
  • 501
  • 6
  • 15
1

Step by step to setup zxing 3.2.1 in eclipse

  1. Download zxing-master.zip from "https://github.com/zxing/zxing"
  2. Unzip zxing-master.zip, Use eclipse to import "android" project in zxing-master
  3. Download core-3.2.1.jar from "http://repo1.maven.org/maven2/com/google/zxing/core/3.2.1/"
  4. Create "libs" folder in "android" project and paste cor-3.2.1.jar into the libs folder
  5. Click on project: choose "properties" -> "Java Compiler" to change level to 1.7. Then click on "Android" change "Project build target" to android 4.4.2+, because using 1.7 requires compiling with Android 4.4
  6. If "CameraConfigurationUtils.java" don't exist in "zxing-master/android/app/src/main/java/com/google/zxing/client/android/camera/". You can copy it from "zxing-master/android-core/src/main/java/com/google/zxing/client/android/camera/" and paste to your project.
  7. Clean and build project. If your project show error about "switch - case", you should change them to "if - else".
  8. Completed. Clean and build project Reference link: How to use Zxing in android
Community
  • 1
  • 1
Anh Duy
  • 1,004
  • 14
  • 21