38

I want my application to recognize barcodes taken by camera. Is it possible using Android SDK?

Something like this: Barcode Scanner

Janusz
  • 187,060
  • 113
  • 301
  • 369
peter.o
  • 3,460
  • 7
  • 51
  • 77
  • 6
    I think this post may have the answer you need. http://stackoverflow.com/questions/2050263/using-zxing-to-create-an-android-barcode-scanning-app – Mike Yockey Dec 14 '10 at 20:32
  • I have created a simple application which uses ML barcode scanner.You can refer this: https://github.com/Rajan-Lal/ML-Barcode-Scanner – Rajan Jul 01 '20 at 16:09

10 Answers10

25

It's not built into the SDK, but you can use the Zxing library. It's free, open source, and Apache-licensed.

The 2016 recommendation is to use the Barcode API, which also works offline.

Community
  • 1
  • 1
Nathan Schwermann
  • 31,285
  • 16
  • 80
  • 91
  • 4
    Now, it's built into the SDK: https://developers.google.com/vision/barcodes-overview – Dinei Dec 19 '15 at 00:02
  • I got excited at this fact, until I noticed it uses google play services, no use for our warehouse, no google services and no outside internet as a secure network. – dave Jan 15 '16 at 15:16
  • 1
    @dave - The problem being it needs internet to work at all? Thanks. – nsandersen May 05 '16 at 14:12
  • @nsandersen the problem is probably the Play Services requirement. Many devices used in warehouse don't have consumer software, and often no Play Services available. – Marc Plano-Lesay Jan 10 '17 at 09:54
  • But BarCode Api provided by google vision only detects some of the specific formats supported, I want a case, where It can detect anything from the barcode scanned that too in my own app, Is there any way to achieve this ? – B.shruti Jan 22 '18 at 07:09
23

2016 update

With the latest release of Google Play Services, v7.8, you have access to the new Mobile Vision API. That's probably the most convenient way to implement barcode scanning now, and it also works offline.

From the Android Barcode API:

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
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
14

Here is sample code using camera api

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.IOException;
import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.Frame;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;

public class MainActivity extends AppCompatActivity {

TextView barcodeInfo;
SurfaceView cameraView;
CameraSource cameraSource;

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

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


    BarcodeDetector barcodeDetector =
            new BarcodeDetector.Builder(this)
                    .setBarcodeFormats(Barcode.CODE_128)//QR_CODE)
                    .build();

    cameraSource = new CameraSource
            .Builder(this, barcodeDetector)
            .setRequestedPreviewSize(640, 480)
            .build();

    cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {

            try {
                cameraSource.start(cameraView.getHolder());
            } catch (IOException ie) {
                Log.e("CAMERA SOURCE", ie.getMessage());
            }
        }

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

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


    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() {
                        barcodeInfo.setText(    // Update the TextView
                                barcodes.valueAt(0).displayValue
                        );
                    }
                });
            }
        }
    });
}
}

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

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

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

    <TextView
        android:text=" code reader"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/txtContent"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Process"
        android:id="@+id/button"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true" />
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imgview"/>
</LinearLayout>
</RelativeLayout>

build.gradle(Module:app)

add compile 'com.google.android.gms:play-services:7.8.+' in dependencies

Kishor N R
  • 1,521
  • 1
  • 17
  • 23
  • 2
    Works, but if you want to scan QR codes, use Barcode.QR_CODE instead of Barcode.CODE_128 – Oleg Gryb Jan 07 '18 at 01:32
  • Also It is appropriate to use All Formats without effecting performance. – Abdulwahid Sep 04 '18 at 20:46
  • 1
    in a new gradle (3+) add only "vision", *implementation 'com.google.android.gms:play-services-vision:16.2.0'* instead of compile 'com.google.android.gms:play-services:7.8.+' – Natalie Jan 02 '19 at 11:18
11

Here is a sample code: my app uses ZXing Barcode Scanner.

  1. You need these 2 classes: IntentIntegrator and IntentResult

  2. Call scanner (e.g. OnClickListener, OnMenuItemSelected...), "PRODUCT_MODE" - it scans standard 1D barcodes (you can add more).:

    IntentIntegrator.initiateScan(this, 
               "Warning", 
               "ZXing Barcode Scanner is not installed, download?",
               "Yes", "No",
               "PRODUCT_MODE");
    
  3. Get barcode as a result:

    public void onActivityResult(int requestCode, int resultCode, Intent intent) {  
      switch (requestCode) {
      case IntentIntegrator.REQUEST_CODE:
         if (resultCode == Activity.RESULT_OK) {
    
            IntentResult intentResult = 
               IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
    
            if (intentResult != null) {
    
               String contents = intentResult.getContents();
               String format = intentResult.getFormatName();
    
               this.elemQuery.setText(contents);
               this.resume = false;
               Log.d("SEARCH_EAN", "OK, EAN: " + contents + ", FORMAT: " + format);
            } else {
               Log.e("SEARCH_EAN", "IntentResult je NULL!");
            }
         } else if (resultCode == Activity.RESULT_CANCELED) {
            Log.e("SEARCH_EAN", "CANCEL");
         }
      }
    }
    

contents holds barcode number

sth
  • 222,467
  • 53
  • 283
  • 367
peter.o
  • 3,460
  • 7
  • 51
  • 77
7

module app:

implementation 'com.google.zxing:core:3.2.1'

implementation 'com.journeyapps:zxing-android-embedded:3.2.0@aar'

AndroidManifest.xml

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus"/>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    Button BarCode;

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

        BarCode = findViewById(R.id.button_barcode);
        final Activity activity = this;

        BarCode.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                IntentIntegrator intentIntegrator = new IntentIntegrator(activity);
                intentIntegrator.setDesiredBarcodeFormats(intentIntegrator.ALL_CODE_TYPES);
                intentIntegrator.setBeepEnabled(false);
                intentIntegrator.setCameraId(0);
                intentIntegrator.setPrompt("SCAN");
                intentIntegrator.setBarcodeImageEnabled(false);
                intentIntegrator.initiateScan();
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        IntentResult Result = IntentIntegrator.parseActivityResult(requestCode , resultCode ,data);
        if(Result != null){
            if(Result.getContents() == null){
                Log.d("MainActivity" , "cancelled scan");
                Toast.makeText(this, "cancelled", Toast.LENGTH_SHORT).show();
            }
            else {
                Log.d("MainActivity" , "Scanned");
                Toast.makeText(this,"Scanned -> " + Result.getContents(), Toast.LENGTH_SHORT).show();
            }
        }
        else {
            super.onActivityResult(requestCode , resultCode , data);
        }
    }
}
Sajeenthiran
  • 417
  • 5
  • 11
2

You can also use barcodefragmentlib which is an extension of zxing but provides barcode scanning as fragment library, so can be very easily integrated.

Here is the supporting documentation for usage of library

King of Masses
  • 18,405
  • 4
  • 60
  • 77
Abhinava
  • 1,030
  • 9
  • 19
1

With Google Firebase ML Kit's barcode scanning API, you can read data encoded using most standard barcode formats.

https://firebase.google.com/docs/ml-kit/read-barcodes?authuser=0

You can follow this link to read barcodes efficiently.

0

There are two parts in building barcode scanning feature, one capturing barcode image using camera and second extracting barcode value from the image.

Barcode image can be captured from your app using camera app and barcode value can be extracted using Firebase Machine Learning Kit barcode scanning API.

Here is an example app https://www.zoftino.com/android-barcode-scanning-example

Arnav Rao
  • 6,692
  • 2
  • 34
  • 31
0

Firebase Barcode scanning API has been deprecated.

You can use Googles ML Kit to recognize and decode barcodes without help of firebase.

Add in your gradle(app)

implementation 'com.google.mlkit:barcode-scanning:17.1.1'

for more details have a look on this official guideline

Navin Kumar
  • 3,393
  • 3
  • 21
  • 46
-1

I had an issue with the parseActivityForResult arguments. I got this to work:

package JMA.BarCodeScanner;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class JMABarcodeScannerActivity extends Activity {

    Button captureButton;
    TextView tvContents;
    TextView tvFormat;
    Activity activity;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        activity = this;
        captureButton = (Button)findViewById(R.id.capture);
        captureButton.setOnClickListener(listener);
        tvContents = (TextView)findViewById(R.id.tvContents);
        tvFormat = (TextView)findViewById(R.id.tvFormat);
    }

    public void onActivityResult(int requestCode, int resultCode, Intent intent) 
    {  
        switch (requestCode) 
        {
            case IntentIntegrator.REQUEST_CODE:
            if (resultCode == Activity.RESULT_OK) 
            {
                IntentResult intentResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);

                if (intentResult != null) 
                {
                   String contents = intentResult.getContents();
                   String format = intentResult.getFormatName();
                   tvContents.setText(contents.toString());
                   tvFormat.setText(format.toString());

                   //this.elemQuery.setText(contents);
                   //this.resume = false;
                   Log.d("SEARCH_EAN", "OK, EAN: " + contents + ", FORMAT: " + format);
                } else {
                    Log.e("SEARCH_EAN", "IntentResult je NULL!");
                }
            } 
            else if (resultCode == Activity.RESULT_CANCELED) {
                Log.e("SEARCH_EAN", "CANCEL");
            }
        }
    }

    private View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
             IntentIntegrator integrator = new IntentIntegrator(activity);
             integrator.initiateScan();
        }
    };
}

Latyout for Activity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button
        android:id="@+id/capture"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Take a Picture"/>

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/tvContents"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/tvFormat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>
Komal12
  • 3,340
  • 4
  • 16
  • 25