22 mar

Scanning and generating barcodes using ZXING library on Android

logoThe most popular all-in-one codes library for Android is zxing. Everyone used a Barcode scanner app based on this lib. But this library provides also ability to generate codes. In this example I show you how scan 1D code – Code 128. Code 128 is a very popular type of 1D code. After scanning, we obtain scanned information and… encode again to show on Android device for further scanning. Let’s go!

What we need:

  • latest ZXING source code (2.1)
  • Eclipse with ADT, Android SDK

After download source code, we import android project (android folder) as a Eclipse project into workspace.

  1. Mark this project as a library -> Project Properties -> Android -> is Library (x).
  2. Add core.jar from core folder from downloaded sources. Now you should successfully run this project on your emulator or device. We back to this project later. Basing on zxing sources is more convinient way to use this library instead of simple jar importing, because we can:
    • disable „on-first-launch help”:
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.capture);
hasSurface = false;
historyManager = new HistoryManager(this);
historyManager.trimHistory();
inactivityTimer = new InactivityTimer(this);
beepManager = new BeepManager(this);
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
// showHelpOnFirstLaunch();
}
    • rename scan and encode intents:
public static final class Scan {
 /**
 * Send this intent to open the Barcodes app in scanning mode, find a barcode, and return
 * the results.
 */
 public static final String ACTION = "eu.michalu.SCAN";
...

and Encode class

public static final class Encode {
 /**
 * Send this intent to encode a piece of data as a QR code and display it full screen, so
 * that another person can scan the barcode from your screen.
 */
 public static final String ACTION = "eu.michalu.ENCODE";
...

    • disable zxing app menu to prevent app crashes. To do this, you should comment out onCreateOptionsMenu() method in CaptureActivity.java
// @Override
 // public boolean onCreateOptionsMenu(Menu menu) {
 // MenuInflater menuInflater = getMenuInflater();
 // menuInflater.inflate(R.menu.capture, menu);
 // return super.onCreateOptionsMenu(menu);
 // }
  1. We create other New Android Project.  We should link our earlier created library project to new application project. Click right mouse button on project and select Properties. Change tab to 'Android’ and add our zxing library project as library.
  2. We have to copy some codes from Android.manifest file from zxing sources. We need to copy Capture and Encode activity declarations, uses permissions and uses features. Copy them and paste into your app manifest. But our package is different from zxing so we have to fixed activity’s  XML attributes name to be compatibile with our library project package (from android:name=”com.google.zxing.client.android.CaptureActivity” instead of „.CaptureActivity”) and android:name=”com.google.zxing.client.android.encode.EncodeActivity” instead of „.encode.EncodeActivity”). We also have to delete or change EncodeActivity’s android:label in our manifest in new project.
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="eu.michalu.zxingexample"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-permission android:name="android.permission.CAMERA" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.VIBRATE" />
        <uses-permission android:name="android.permission.FLASHLIGHT" />
        <uses-permission android:name="android.permission.READ_CONTACTS" />
        <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    
        <!-- Don't require camera, as this requires a rear camera. This allows it to work on the Nexus 7 -->
        <uses-feature
            android:name="android.hardware.camera"
            android:required="false" />
        <uses-feature
            android:name="android.hardware.camera.front"
            android:required="false" />
        <uses-feature
            android:name="android.hardware.camera.autofocus"
            android:required="false" />
        <uses-feature
            android:name="android.hardware.camera.flash"
            android:required="false" />
        <uses-feature android:name="android.hardware.screen.landscape" />
        <uses-feature
            android:name="android.hardware.wifi"
            android:required="false" />
        <uses-feature
            android:name="android.hardware.touchscreen"
            android:required="false" />
    
        <!-- Donut-specific flags which allow us to run on any dpi screens. -->
        <supports-screens
            android:anyDensity="true"
            android:largeScreens="true"
            android:normalScreens="true"
            android:smallScreens="true"
            android:xlargeScreens="true" />
    
        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="17" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="eu.michalu.zxingexample.MainActivity"
                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:clearTaskOnLaunch="true"
                android:configChanges="orientation|keyboardHidden"
                android:screenOrientation="landscape"
                android:stateNotNeeded="true"
                android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                android:windowSoftInputMode="stateAlwaysHidden" >
                <intent-filter>
                    <action android:name="eu.michalu.SCAN" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
                <!-- Allow web apps to launch Barcode Scanner by linking to http://zxing.appspot.com/scan. -->
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="android.intent.category.BROWSABLE" />
    
                    <data
                        android:host="zxing.appspot.com"
                        android:path="/scan"
                        android:scheme="http" />
                </intent-filter>
                <!-- We also support a Google Product Search URL. -->
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="android.intent.category.BROWSABLE" />
    
                    <data
                        android:host="www.google.com"
                        android:path="/m/products/scan"
                        android:scheme="http" />
                </intent-filter>
                <!-- And the UK version. -->
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="android.intent.category.BROWSABLE" />
    
                    <data
                        android:host="www.google.co.uk"
                        android:path="/m/products/scan"
                        android:scheme="http" />
                </intent-filter>
                <!-- Support zxing://scan/?... like iPhone app -->
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="android.intent.category.BROWSABLE" />
    
                    <data
                        android:host="scan"
                        android:path="/"
                        android:scheme="zxing" />
                </intent-filter>
            </activity>
            <activity
                android:name="com.google.zxing.client.android.encode.EncodeActivity"
                android:stateNotNeeded="true" >
                <intent-filter>
                    <action android:name="eu.michalu.ENCODE" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
                <!-- This allows us to handle the Share button in Contacts. -->
                <intent-filter>
                    <action android:name="android.intent.action.SEND" />
    
                    <category android:name="android.intent.category.DEFAULT" />
    
                    <data android:mimeType="text/x-vcard" />
                </intent-filter>
                <!-- This allows us to handle sharing any plain text . -->
                <intent-filter>
                    <action android:name="android.intent.action.SEND" />
    
                    <category android:name="android.intent.category.DEFAULT" />
    
                    <data android:mimeType="text/plain" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    
  3. Now we have to put some code in our MainActivity. After create activity we would like to immidietely open an included barcode scanner with scan function. So we create an intent and specify some parameters as shown below:
package eu.michalu.zxingexample;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
public class MainActivity extends Activity {
public static final int SCANNER_RESULT = 111;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 Intent intent = new Intent(&quot;eu.michalu.SCAN&quot;);
 intent.putExtra(&quot;SCAN_MODE&quot;, &quot;ONE_D_MODE&quot;);
 startActivityForResult(intent, SCANNER_RESULT);
 }
  1. After successfully scanning, we should get and process obtaining data in onActivityResult method:
@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
 super.onActivityResult(requestCode, resultCode, intent);
 /**
 * Back from scanner view
 */
 if (requestCode == SCANNER_RESULT) {
 if (resultCode == RESULT_OK) {
 String contents = intent.getStringExtra(&quot;SCAN_RESULT&quot;);
 Intent encodeIntent = new Intent(&quot;eu.michalu.ENCODE&quot;);
 encodeIntent.addCategory(Intent.CATEGORY_DEFAULT);
 encodeIntent.putExtra(&quot;ENCODE_FORMAT&quot;, &quot;CODE_128&quot;);
 encodeIntent.putExtra(&quot;ENCODE_DATA&quot;, contents);
 startActivity(encodeIntent);
} else if (resultCode == RESULT_CANCELED) {
 // Handle cancel
 Log.i(MainActivity.class.getSimpleName(), &quot;Handle cancel&quot;);
 }
 }
 }

Test

  1. Create CODE128 using online generator i.e. http://www.barcoding.com/upc/ and scan using our example app. After scanning you should get the same CODE128 like this online generated one.
    0123456789
  2. Scanning …

scanning

  1. and encoded again our code! 🙂

encoded

Full source code of application, library and apk:

or checkout from my github account:

github_logo

3 thoughts on “Scanning and generating barcodes using ZXING library on Android

  1. This is a great work!…I would like to add some things to work with zxing 3.2

    1- copy CameraConfigurationUtils.java from zxing project y paste in package com.google.zxing.client.android.camera
    2- clean zxing project
    3- if there are some errors on the classes replace „case” for „if else”
    4- In our project Go to Properties -> Java Build Path -> „Order and Export” Then order the core.jar to the first position and select it!
    you must clean your project after your operation. Project -> clean

    well that work for me.

    sorry for my poor english.

    Thanks for all!
    best regards!

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *