Integrating ZXing in our own Android app: BarcodeScanner


For some time, I’ve been considering how to integrate Zxing barcode scanner in a project without having installed an extra app to use it (although they give you the chance to use an intent to test if Barcode Scanner is installed and use it). One of ZXing’s creators gave us some reasons of why not to do this, and if you want you can read them here

However, my inquisitiveness led me to think how could I integrate the code inside a project. Some of the reasons I thought it was very helpful are:

  • Chances to customize the UI of the barcode scanner.
  • When the project is large enough, it could be easier to share the data model with ZXing (This is more important that you could think…

All of this is possible thanks to Sean Owen (I think he’s the creator, and I don’t know who else participated in this project, so sorry if I missed someone!), and the Apache 2.0 license.

First of all, we have to download Zxing’s source code to integrate it. You can download it here

Once we downloaded it, unzip it, and we’ll copy the source code (the one that’s inside android folder) into our project and link thecore.jarlibrary (inside core folder).

We’ll create a new source folder to put the ZXing’s source code, and other to put the libraries (this time, they’ll be only those that ZXing needs. Our workspace should be something like this:


We can see to many errors there… That’s because ZXing resources are not declared yet.

Here’s when the “funniest” part. We’ll declare the activity in the AndroidManifest.xml as we can see in this snippet:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="es.jmanzano"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".ZxingExampleActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.google.zxing.client.android.CaptureActivity"
            android:label="ZXing"/>
    </application>

</manifest>

Besides camera permission, ZXing use more but for this example they’re not necessary. You must explore ZXing and think about which of those permissions declared by ZXing you’ll use (they can be found in ZXing’s AndroidManifest.xml).

Now, we could use the QR Scanner activity… If there were not so many errors in the project.

Next part is the easiest (depending on the projects size): We have to mix ZXing’s resources with ours.. That is, all the layouts, strings.xml, attrs.xml, etc… have to be mixed with ours. Here, what we’ll take into account is that there could be resource’s names that are in both projects. Then, we’ll simply erase one of those. If the project is completely new, it’ll be easier: we only have to copy ZXing’s res folder to our project..

Finally we’ll have to change some lines of ZXing’s source code. References to R are wrong (import com.google.zxing.client.android.R;
) and we’ll have to make them right. So, in my project, I’ll have to include the following snippet in files were it’s needed:

import es.jmanzano.R;

To make an example, we’ve made an activity that looks like this (with its main.xml)

package es.jmanzano;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

import com.google.zxing.client.android.CaptureActivity;

public class ZxingExampleActivity extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	public void onClick(View view) {
		Intent intent = new Intent(getApplicationContext(),
				CaptureActivity.class);
		startActivity(intent);
	}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="ZXing launcher!" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="start ZXing activity"/>

</LinearLayout>


After doing all of this, we can explore ZXing’s code and modify it. There are two classes that we can investigate::

  • CaptureActivity: Main Activity responsible for displaying the scanning screen. We should pay attention to handleDecodeExternally() method in which we could do what we want with the barcode, qr code, etc.. read.
  • ViewfinderView: This will be the layer that be overlaid to camera preview, and the one in which we can do all the changes to the scanning UI.

I hope you like the article, and you can ask me any doubt, follow me on twitter twitter or write me and email.



 


33 thoughts on Integrating ZXing in our own Android app: BarcodeScanner

  1. While I appreciate this was posted in good faith to help people, we actually strongly discourage a pure copy and paste of the Barcode Scanner app. We have a big problem with near 100% clones in the Android Market, some malware. Less perniciously, people who copy the UI into their app make users think they’re using Barcode Scanner when they’re not. This creates support burden for apps that aren’t ours, and is a legal trademark problem.

    We do encourage anyone to use the core decoding/encoding library in their own app. We encourage everyone to reuse parts of the Android app in building their own app if needed. The key word is “their app”: write your own from scratch and add our code as needed. Don’t start from ours and you’ll be in a much better place.

    • I didn’t see this reply.

      Thank you for your comment, and as I mentioned in the article, there are other ways of doing this (that can be better or worse), but I wanted to write something that some people would like to read.

      Thanks again!

    • I didn’t see this reply. =(

      Thank you for your comment, and as I mentioned in the article, there are other ways of doing this (that can be better or worse), but I wanted to write something that some people would like to read.

      Thanks again!

    • You can download it from zxing’s google code page.. In downloads section, download the version you’re looking for (1.7 or 2.0), unzip it, and there you have it in one of the folders inside (I think it’s called core)

  2. Why this code is not working on my HTC desire HD. The scanner continuously focuses and re-focuses and fails to read the bar-code. I have checked with another device and Its working fine.. pls help!!!! :sad: :sad: :sad:

    • It depends on the device, but i could try it on many device (the ZXing Barcode Scanner base application) and it works flawlessly on : Galaxy S, Galaxy Tab, Galaxy S Wifi 4&5 but on Galaxy SIII and Google Nexus 7 (frontal camera) the focus just doesn’t react and so it never worked. Some optimizations need to be done on some devices, or maybe it will never work on those…

  3. Thanks for the great article~ I initially went through the steps written under http://damianflannery.wordpress.com/2011/06/13/integrate-zxing-barcode-scanner-into-your-android-app-natively-using-eclipse/, and end up with bugs which stopped me from compilation. When I come to your post, I see the problem, which is like what you mentioned: “We can see to many errors there… That’s because ZXing resources are not declared yet.”

    But question is, those errors are not fixed, any idea on how to overcome those? because if it remains with the errors, eclipse can’t compile it. What should I do with the errors?

  4. i followed all the instructions but when i click the button in the activity it not working(force to close). In log-cat show following error:

    08-21 11:59:25.895: E/AndroidRuntime(909): FATAL EXCEPTION: main
    08-21 11:59:25.895: E/AndroidRuntime(909): java.lang.ExceptionInInitializerError
    08-21 11:59:25.895: E/AndroidRuntime(909): at java.lang.Class.newInstanceImpl(Native Method)
    08-21 11:59:25.895: E/AndroidRuntime(909): at java.lang.Class.newInstance(Class.java:1409)
    08-21 11:59:25.895: E/AndroidRuntime(909): at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
    08-21 11:59:25.895: E/AndroidRuntime(909): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1561)
    08-21 11:59:25.895: E/AndroidRuntime(909): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
    08-21 11:59:25.895: E/AndroidRuntime(909): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    08-21 11:59:25.895: E/AndroidRuntime(909): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
    08-21 11:59:25.895: E/AndroidRuntime(909): at android.os.Handler.dispatchMessage(Handler.java:99)
    08-21 11:59:25.895: E/AndroidRuntime(909): at android.os.Looper.loop(Looper.java:123)
    08-21 11:59:25.895: E/AndroidRuntime(909): at android.app.ActivityThread.main(ActivityThread.java:3683)
    08-21 11:59:25.895: E/AndroidRuntime(909): at java.lang.reflect.Method.invokeNative(Native Method)
    08-21 11:59:25.895: E/AndroidRuntime(909): at java.lang.reflect.Method.invoke(Method.java:507)
    08-21 11:59:25.895: E/AndroidRuntime(909): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    08-21 11:59:25.895: E/AndroidRuntime(909): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    08-21 11:59:25.895: E/AndroidRuntime(909): at dalvik.system.NativeStart.main(Native Method)
    08-21 11:59:25.895: E/AndroidRuntime(909): Caused by: java.lang.NoClassDefFoundError: com.google.zxing.ResultMetadataType
    08-21 11:59:25.895: E/AndroidRuntime(909): at com.google.zxing.client.android.CaptureActivity.(CaptureActivity.java:108)
    08-21 11:59:25.895: E/AndroidRuntime(909): … 15 more

    please tell me what i have done wrong?

  5. Hi guys, thank you for the tutorial but I am still confused (don’t worry it doesn’t take much). I have very little knowledge of coding and am very new to creating andoid app. I using Buzztouch with eclipse to create my app, and my final step is to “intergrate” a bar code scanner. Walking through the above I don’t really understand at the point “change some lines of ZXing’s source code” I don’t see the references to “R”. Also I am totally lost with the whole activity part and getting a button to launch the scanner. I also couldn’t find the “main.xml” file. Sorry to be such a noobie, but if I can get this to work it would be amazing. Any help would be appreciated.
    Thanks.
    Howard

  6. when i integrate this zxing bar code in my application one image which is used in my application hides the camera view.I don’t know how to fix it please any one tell me y this happened?….

  7. Hi,

    thanks a lot for the blog. It’s very helpful however in this step: ‘Finally we’ll have to change some lines of ZXing’s source code. References to R are wrong (import com.google.zxing.client.android.R; ‘

    I am having problems as when I checked in the source files for Zxing there is no import declaration which states: com.google.zxing.client.android.R hence I cannot change it. And, When I copied the source code from the unzipped zxing folder into my android project I am getting all the source files but it is not displaying as in the blog (with the different packages e.g. com.google.zxing.client.android) etc… For me it shows all of these as folders in the same hierarchical structure so it shows com folder > google>zxing>client>android etc… and I think because of this the reference to the captureactivity class is not working. Can someone please help?

    Thanks in advance
    Pooja

    • i made it work, it was very confusing a a bit of tweaking the minifest and imports.

      capture activity is the one you need to import .R from your current package.

      In the Library project too, all references to .R should be pointing to yourpackage.R
      there were some files where eclipse suggested changing the switch to if/else.
      Also, you should pay attention declaring the activities in the androidmanifest + permissions.

      go for it, it works !

  8. Congrulations for you article ,it’s great.
    I was searching for days the solution but finally i solved.But however i have an small problem.Once i read the code , in my screen appears 3 options:1) Send via sms , 2)share via e-mail and the last one , 3)search on the web.

    I want the read input go directly to my textview and not sshowing these options i am mentioning now.Could you help?

    Intent intent = new Intent(getApplicationContext(),CaptureActivity.class);
    intent.putExtra(“SCAN_MODE”, “PRODUCT_MODE”);
    startActivityForResult(intent, 0);

    and the next funcion is onActivityResult
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == 0) {
    if (resultCode == 1) { //RESULT_OK o 1
    String cap = intent.getStringExtra(“RESULT”);
    this.tvStatus.setText(intent.getStringExtra(“SCAN_RESULT_FORMAT”));
    this.tvResult.setText(intent.getStringExtra(“SCAN_RESULT”)+cap);
    Toast.makeText(Lector_demoActivity.this,
    “Scan Result:” + cap, Toast.LENGTH_SHORT)
    .show();
    // Hacer algo con los datos obtenidos.
    } else if (resultCode == RESULT_CANCELED) {
    this.tvStatus.setText(“Press a button to start a scan.”);
    this.tvResult.setText(“Scan cancelled.”);
    }
    }
    }

  9. hey dear i followed your tut but got stucked finding a solution for “force close exception”.

    pls anyone knows the solution plz replay..
    Thanx in advance

    My logcat output
    —————
    11-29 12:34:54.740: D/AndroidRuntime(1970): Shutting down VM
    11-29 12:34:54.740: W/dalvikvm(1970): threadid=1: thread exiting with uncaught exception (group=0×40015560)
    11-29 12:34:54.761: E/AndroidRuntime(1970): FATAL EXCEPTION: main
    11-29 12:34:54.761: E/AndroidRuntime(1970): java.lang.RuntimeException: Unable to resume activity {com.example.barcodesankalp/com.google.zxing.client.android.CaptureActivity}: java.lang.NullPointerException
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2095)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2110)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1643)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:928)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.os.Handler.dispatchMessage(Handler.java:99)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.os.Looper.loop(Looper.java:123)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.app.ActivityThread.main(ActivityThread.java:3647)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at java.lang.reflect.Method.invokeNative(Native Method)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at java.lang.reflect.Method.invoke(Method.java:507)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at dalvik.system.NativeStart.main(Native Method)
    11-29 12:34:54.761: E/AndroidRuntime(1970): Caused by: java.lang.NullPointerException
    11-29 12:34:54.761: E/AndroidRuntime(1970): at com.google.zxing.client.android.CaptureActivity.resetStatusView(CaptureActivity.java:686)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at com.google.zxing.client.android.CaptureActivity.onResume(CaptureActivity.java:183)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1149)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.app.Activity.performResume(Activity.java:3833)
    11-29 12:34:54.761: E/AndroidRuntime(1970): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2085)
    11-29 12:34:54.761: E/AndroidRuntime(1970): … 12 more
    11-29 12:34:57.810: I/Process(1970): Sending signal. PID: 1970 SIG: 9

  10. After couple hours, I finally find that the com.google.zxing.client.android.CaptureActivity (Android Manifest) must have android:screenOrientation=”landscape”, because it only support this Orientation.

  11. On CaptureActivity is something wrong with me,error was Caused by: java.lang.NoClassDefFoundError: com.google.zxing.ResultMetadataType


    EnumSet.of(ResultMetadataType.ISSUE_NUMBER,
    ResultMetadataType.SUGGESTED_PRICE,
    ResultMetadataType.ERROR_CORRECTION_LEVEL,
    ResultMetadataType.POSSIBLE_COUNTRY);

  12. I have followed your tutorial but I have an error in my project:
    “R cannot be resolved to a variable”.

    Except src folder we also need strings, drawables etc.
    How I need to copy zxing project?

  13. Pingback: Implementing Barcode Scanner : Android Community - For Application Development

  14. How to scan QRCode, my code is:

    public class ScannerQR extends CaptureActivity {

    private String code;

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

    @Override
    public void handleDecode(Result rawResult, Bitmap barcode) {
    Toast.makeText(this.getApplicationContext(), "QR code: " + rawResult.getText(), Toast.LENGTH_LONG).show();
    }

  15. How to only scan QRCode, my code is:

    public class ScannerQR extends CaptureActivity {

    private String code;

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

    @Override
    public void handleDecode(Result rawResult, Bitmap barcode) {
    Toast.makeText(this.getApplicationContext(), "QR code: " + rawResult.getText(), Toast.LENGTH_LONG).show();
    }

  16. Dear all,

    Can anyone help me out of the following error which was faced by Manas posted on 29 November, 2012 at 7:11 am.

    I also facing that same problem:-

    Thank you.

    My logcat output:-

    02-14 12:52:51.391: D/AndroidRuntime(592): Shutting down VM
    02-14 12:52:51.421: W/dalvikvm(592): threadid=1: thread exiting with uncaught exception (group=0x409961f8)
    02-14 12:52:51.582: E/AndroidRuntime(592): FATAL EXCEPTION: main
    02-14 12:52:51.582: E/AndroidRuntime(592): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.rsa.cardova/com.google.zxing.client.android.CaptureActivity}: java.lang.ClassNotFoundException: com.google.zxing.client.android.CaptureActivity
    02-14 12:52:51.582: E/AndroidRuntime(592): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1879)
    02-14 12:52:51.582: E/AndroidRuntime(592): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
    02-14 12:52:51.582: E/AndroidRuntime(592): at android.app.ActivityThread.access$600(ActivityThread.java:122)
    02-14 12:52:51.582: E/AndroidRuntime(592): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
    02-14 12:52:51.582: E/AndroidRuntime(592): at android.os.Handler.dispatchMessage(Handler.java:99)
    02-14 12:52:51.582: E/AndroidRuntime(592): at android.os.Looper.loop(Looper.java:137)
    02-14 12:52:51.582: E/AndroidRuntime(592): at android.app.ActivityThread.main(ActivityThread.java:4340)
    02-14 12:52:51.582: E/AndroidRuntime(592): at java.lang.reflect.Method.invokeNative(Native Method)
    02-14 12:52:51.582: E/AndroidRuntime(592): at java.lang.reflect.Method.invoke(Method.java:511)
    02-14 12:52:51.582: E/AndroidRuntime(592): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    02-14 12:52:51.582: E/AndroidRuntime(592): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    02-14 12:52:51.582: E/AndroidRuntime(592): at dalvik.system.NativeStart.main(Native Method)
    02-14 12:52:51.582: E/AndroidRuntime(592): Caused by: java.lang.ClassNotFoundException: com.google.zxing.client.android.CaptureActivity
    02-14 12:52:51.582: E/AndroidRuntime(592): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
    02-14 12:52:51.582: E/AndroidRuntime(592): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    02-14 12:52:51.582: E/AndroidRuntime(592): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    02-14 12:52:51.582: E/AndroidRuntime(592): at android.app.Instrumentation.newActivity(Instrumentation.java:1023)
    02-14 12:52:51.582: E/AndroidRuntime(592): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1870)
    02-14 12:52:51.582: E/AndroidRuntime(592): … 11 more
    02-14 12:52:56.491: I/Process(592): Sending signal. PID: 592 SIG: 9

  17. Once i read the code , in my screen appears 3 options:1) Send via sms , 2)share via e-mail and the last one , 3)search on the web.

    I want the read input go directly to my textview and not sshowing these options i am mentioning now.Could you help?

    Intent intent = new Intent(getApplicationContext(),CaptureActivity.class);
    intent.putExtra(“SCAN_MODE”, “PRODUCT_MODE”);
    startActivityForResult(intent, 0);

    and the next funcion is onActivityResult
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == 0) {
    if (resultCode == 1) {
    // Handle successful scan
    String capturedQrValue = intent.getStringExtra(“RESULT”);
    //String format = intent.getStringExtra(“SCAN_RESULT_FORMAT”);
    Toast.makeText(MainActivity.this,
    “Scan Result:” + capturedQrValue, Toast.LENGTH_SHORT)
    .show();

    } else if (resultCode == RESULT_CANCELED) {
    // Handle cancel
    }
    } else {

    }
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>