First Android App | Step 8 | ZBar Barcode Scanning in Android Example

In this session, we are going to see how ZBar can be integrated an Android Application. ZBar is one of the most prominent Free Barcode Scanners available.

The following video explains to you step by step on how to implement the same.




Source Code

AndroidManifest.xml

 Add the following lines
Add another activity within

      <activity 
            android:label="@string/barcode" 
            android:launchmode="singleTop" 
            android:name="com.zing.basket.Barcode" 
            android:screenorientation="portrait" 
            android:theme="@android:style/Theme.Dialog">
        </activity>

Add the following permissions
    
    <uses-permission android:name="android.permission.CAMERA">
    <uses-feature android:name="android.hardware.camera">
    <uses-feature android:name="android.hardware.camera.autofocus">


In res/values/strings.xml, add the following line.

<string name="barcode">Barcode Scanning...</string>

Create a new file in src folder called Barcode.java

package com.zing.basket;

import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Handler;
import android.widget.FrameLayout;

public class Barcode extends Activity{

 private Camera mCamera;
    private CameraPreview mPreview;
    private Handler autoFocusHandler;
    
    ImageScanner scanner;
    private boolean barcodeScanned = false;
    private boolean previewing = true;
    
    public void onCreate(Bundle savedInstanceState) 
    {
        
        setContentView(R.layout.activity_barcode);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        
        //getActionBar().hide();
  
        autoFocusHandler = new Handler();
        mCamera = getCameraInstance();
        // Instance barcode scanner
        scanner = new ImageScanner();
        scanner.setConfig(0, Config.X_DENSITY, 400);
        scanner.setConfig(0, Config.Y_DENSITY, 400);
        scanner.setConfig(0, Config.ENABLE, 0);
        scanner.setConfig(Symbol.EAN13, Config.ENABLE,1);
        scanner.setConfig(Symbol.EAN8, Config.ENABLE,1);
        scanner.setConfig(Symbol.UPCA, Config.ENABLE,1);
        scanner.setConfig(Symbol.UPCE, Config.ENABLE,1);
        
        mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
        FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
        preview.addView(mPreview);
        
        super.onCreate(savedInstanceState);
    }

    
    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance()
    {
        Camera c = null;
        try 
        {
            c = Camera.open();
        } catch (Exception e)
        {
         //nada
        }
        return c;
    }
 
    private void releaseCamera() 
    {
        if (mCamera != null) 
        {
            previewing = false;
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
        }
    }

   
    
    PreviewCallback previewCb = new PreviewCallback() 
    {
        public void onPreviewFrame(byte[] data, Camera camera) 
        {
            Camera.Parameters parameters = camera.getParameters();
            Size size = parameters.getPreviewSize();
            Image barcode = new Image(size.width, size.height, "Y800");
            barcode.setData(data);
            int result = scanner.scanImage(barcode);
            if (result != 0) 
            {
                previewing = false;
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                SymbolSet syms = scanner.getResults();
                for (Symbol sym : syms) 
                {
                    barcodeScanned = true;
                    
                    Intent returnIntent = new Intent();
                    returnIntent.putExtra("BARCODE", sym.getData());
                    setResult(1,returnIntent);
                    releaseCamera();
                    finish();
                }
            }
        }
    };
    
    // Mimic continuous auto-focusing
    AutoFocusCallback autoFocusCB = new AutoFocusCallback() 
    {
        public void onAutoFocus(boolean success, Camera camera) 
        {
            autoFocusHandler.postDelayed(doAutoFocus, 1000);
        }
    };
    
    private Runnable doAutoFocus = new Runnable() 
    {
        public void run() 
        {
            if (previewing)
                mCamera.autoFocus(autoFocusCB);
        }
    };
    
    public void onPause() 
    {
        super.onPause();
        releaseCamera();
    }

    @Override
    public void onBackPressed() {
     
     releaseCamera();
     Intent intent = new Intent();
        intent.putExtra("BARCODE","NULL");
        setResult(RESULT_OK, intent);
        super.onBackPressed();
    }

    
}


Create a new file in src folder called CameraPreview.java

package com.zing.basket;

import java.io.IOException;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback 
{

    private SurfaceHolder mHolder;
    private Camera mCamera;
    private PreviewCallback previewCallback;
    private AutoFocusCallback autoFocusCallback;
   
    
    public CameraPreview(Context context, Camera camera,PreviewCallback previewCb,AutoFocusCallback autoFocusCb) 
    {
        super(context);
        mCamera = camera;
        previewCallback = previewCb;
        autoFocusCallback = autoFocusCb;
 
        // Set camera to continuous focus if supported, otherwise use
        // software auto-focus. Only works for API level >=9.
 
        // Camera.Parameters parameters = camera.getParameters();
        // for (String f : parameters.getSupportedFocusModes()) {
        //     if (f == Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
        //         mCamera.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        //         autoFocusCallback = null;
        //         break;
        //     }
        // }
         
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.

        mHolder = getHolder();
        mHolder.addCallback(this);
 
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    } 
 
    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try 
        {
            mCamera.setPreviewDisplay(holder);
        } catch (IOException e) {
            Log.d("DBG", "Error setting camera preview: " + e.getMessage());
        }
    }
 
    public void surfaceDestroyed(SurfaceHolder holder) 
    {
        // Camera preview released in activity
    }
 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        /*
         * If your preview can change or rotate, take care of those events here.
         * Make sure to stop the preview before resizing or reformatting it.
         */
        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }
        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }
        try {
            // Hard code camera surface rotation 90 degs to match Activity view in portrait
            mCamera.setDisplayOrientation(90);
 
            mCamera.setPreviewDisplay(mHolder);
            mCamera.setPreviewCallback(previewCallback);
            mCamera.startPreview();
            mCamera.autoFocus(autoFocusCallback);
        } catch (Exception e){
            Log.d("DBG", "Error starting camera preview: " + e.getMessage());
        }
    }
}


Make the changes in Search.java.

1. Add 2 methods onActivityResult to receive the scanned barcode back from Barcode Activity
2. buttonBarcode.setOnClickListener to call the Barcode Activity.

package com.zing.basket;

import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
import android.widget.Toast;

import com.zing.basket.util.Product;



public class Search extends Fragment
{
 View myFragmentView;
 SearchView search;
 ImageButton buttonBarcode;
 ImageButton buttonAudio;
 Typeface type;
 ListView searchResults;
 String found = "N";
 
 
 //This arraylist will have data as pulled from server. This will keep cumulating.
 ArrayList<Product> productResults = new ArrayList<Product>();
 //Based on the search string, only filtered products will be moved here from productResults
 ArrayList<Product> filteredProductResults = new ArrayList<Product>();
 
 @Override
 public void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
 }
 
 
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
 Bundle savedInstanceState) 
 {
  //get the context of the HomeScreen Activity
  final HomeScreen activity = (HomeScreen) getActivity();
  
  //define a typeface for formatting text fields and listview. 
  
  type= Typeface.createFromAsset(activity.getAssets(),"fonts/book.TTF");
  myFragmentView = inflater.inflate(R.layout.fragment_search, container, false);  
     
  search=(SearchView) myFragmentView.findViewById(R.id.searchView1);
        search.setQueryHint("Start typing to search...");
        
        search.setIconifiedByDefault(false);
        
  searchResults = (ListView) myFragmentView.findViewById(R.id.listview_search);
  buttonBarcode = (ImageButton) myFragmentView.findViewById(R.id.imageButton2);
  buttonAudio = (ImageButton) myFragmentView.findViewById(R.id.imageButton1);
  
  
  //this part of the code is to handle the situation when user enters any search criteria, how should the 
  //application behave?
  
  buttonBarcode.setOnClickListener(new OnClickListener() 
        {
            public void onClick(View v) 
            {
             startActivityForResult(new Intent(activity, Barcode.class),1); 
            }
        });
  
  search.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() 
        {
      
      @Override
      public void onFocusChange(View v, boolean hasFocus) {
       // TODO Auto-generated method stub
        
       //Toast.makeText(activity, String.valueOf(hasFocus),Toast.LENGTH_SHORT).show();
      }
     });
  
  search.setOnQueryTextListener(new OnQueryTextListener() 
        {
       
      @Override
      public boolean onQueryTextSubmit(String query) {
       // TODO Auto-generated method stub
        
       return false;
      }
      
      @Override
      public boolean onQueryTextChange(String newText) {
       
        if (newText.length() > 3)
        {
         
         searchResults.setVisibility(myFragmentView.VISIBLE);
         myAsyncTask m= (myAsyncTask) new myAsyncTask().execute(newText);
        }
        else
        {
         
         searchResults.setVisibility(myFragmentView.INVISIBLE);
        }
       
       
               
       return false;
      }
      
     });
  return myFragmentView;
 }  
 
 //this captures the result from barcode and populates in the searchView. 
 @Override  
    public void onActivityResult(int requestCode, int resultCode, Intent data)  
    {  
          
  //Log.d("arindam","insideOnActivityResult");
  //super.onActivityResult(requestCode, resultCode, data);    
        if(requestCode==1)  
        {  
         String barcode=data.getStringExtra("BARCODE");
         if (barcode.equals("NULL"))
         {
          //that means barcode could not be identified or user pressed the back button
          //do nothing 
         }
         else
         {
          search.setQuery(barcode, true);
          search.setIconifiedByDefault(false);
         }
        }
          
    } 
 
 //this filters products from productResults and copies to filteredProductResults based on search text 

 public void filterProductArray(String newText) 
 {

  String pName;
  
  filteredProductResults.clear();
  for (int i = 0; i < productResults.size(); i++)
  {
   pName = productResults.get(i).getProductName().toLowerCase();
   if ( pName.contains(newText.toLowerCase()) ||
     productResults.get(i).getProductBarcode().contains(newText))
   {
    filteredProductResults.add(productResults.get(i));

   }
  }
  
 }
 
 //in this myAsyncTask, we are fetching data from server for the search string entered by user.
 class myAsyncTask extends AsyncTask<String, Void, String> 
 {
  JSONParser jParser;
  JSONArray productList;
  String url=new String();
  String textSearch;
  ProgressDialog pd;


  @Override
  protected void onPreExecute() {
   super.onPreExecute();
   productList=new JSONArray();
   jParser = new JSONParser();
   pd= new ProgressDialog(getActivity());
   pd.setCancelable(false);
   pd.setMessage("Searching...");
   pd.getWindow().setGravity(Gravity.CENTER);
   pd.show();
  }

  @Override
  protected String doInBackground(String... sText) {
   
   url="http://lawgo.in/lawgo/products/user/1/search/"+sText[0];
   String returnResult = getProductList(url);
   this.textSearch = sText[0];
   return returnResult;
   
  }

  public String getProductList(String url)
  {
   
   Product tempProduct = new Product();
   String matchFound = "N";
   //productResults is an arraylist with all product details for the search criteria
   //productResults.clear();
   
   
   try {
    
    
    JSONObject json = jParser.getJSONFromUrl(url);
    
    productList = json.getJSONArray("ProductList");
  
    //parse date for dateList 
    for(int i=0;i<productList.length();i++)
    {
     tempProduct = new Product();
     
     JSONObject obj=productList.getJSONObject(i);
     
     tempProduct.setProductCode(obj.getString("ProductCode"));
     tempProduct.setProductName(obj.getString("ProductName"));
     tempProduct.setProductGrammage(obj.getString("ProductGrammage"));
     tempProduct.setProductBarcode(obj.getString("ProductBarcode"));
     tempProduct.setProductDivision(obj.getString("ProductCatCode"));
     tempProduct.setProductDepartment(obj.getString("ProductSubCode"));
     tempProduct.setProductMRP(obj.getString("ProductMRP"));
     tempProduct.setProductBBPrice(obj.getString("ProductBBPrice"));
     
     //check if this product is already there in productResults, if yes, then don't add it again. 
     matchFound = "N";
     
     for (int j=0; j < productResults.size();j++)
     {
      
      if (productResults.get(j).getProductCode().equals(tempProduct.getProductCode()))
      {
       matchFound = "Y";    
      }
     }
     
     if (matchFound == "N")
     {
       productResults.add(tempProduct);
     }
     
    }
    
    return ("OK");
    
   } catch (Exception e) {
    e.printStackTrace();
    return ("Exception Caught");
   }
  }
  
  @Override
  protected void onPostExecute(String result) {

   super.onPostExecute(result);
   
   if(result.equalsIgnoreCase("Exception Caught"))
   {
    Toast.makeText(getActivity(), "Unable to connect to server,please try later", Toast.LENGTH_LONG).show();

    pd.dismiss();
   }
   else
   {
  
    
    //calling this method to filter the search results from productResults and move them to 
    //filteredProductResults
    filterProductArray(textSearch);
    searchResults.setAdapter(new SearchResultsAdapter(getActivity(),filteredProductResults));
    pd.dismiss();
   }
  }

 }
}

class SearchResultsAdapter extends BaseAdapter
{
  private LayoutInflater layoutInflater;
  
  private ArrayList<Product> productDetails=new ArrayList<Product>();
  int count;
  Typeface type;
  Context context;
  
  //constructor method
 public SearchResultsAdapter(Context context, ArrayList<Product> product_details) {
 
  layoutInflater = LayoutInflater.from(context);
 
   this.productDetails=product_details;
   this.count= product_details.size();
   this.context = context;
   type= Typeface.createFromAsset(context.getAssets(),"fonts/book.TTF");
   
 }

 @Override
 public int getCount() {
  return count;
 }

 @Override
 public Object getItem(int arg0) {
  return productDetails.get(arg0);
 }

 @Override
 public long getItemId(int arg0) {
  return arg0;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) 
 {
  
   ViewHolder holder;
      Product tempProduct = productDetails.get(position);
      
   if (convertView == null) 
      {
       convertView = layoutInflater.inflate(R.layout.listtwo_searchresults, null);
          holder = new ViewHolder();
          holder.product_name = (TextView) convertView.findViewById(R.id.product_name);
          holder.product_mrp = (TextView) convertView.findViewById(R.id.product_mrp);
          holder.product_mrpvalue = (TextView) convertView.findViewById(R.id.product_mrpvalue);
          holder.product_bb = (TextView) convertView.findViewById(R.id.product_bb);
          holder.product_bbvalue = (TextView) convertView.findViewById(R.id.product_bbvalue);
          holder.addToCart = (Button) convertView.findViewById(R.id.add_cart);

    convertView.setTag(holder);
      } 
   else 
      {
             holder = (ViewHolder) convertView.getTag();
      }
  
       
   holder.product_name.setText(tempProduct.getProductName());
   holder.product_name.setTypeface(type);
      
   holder.product_mrp.setTypeface(type);
   
   holder.product_mrpvalue.setText(tempProduct.getProductMRP());
   holder.product_mrpvalue.setTypeface(type);
   
   holder.product_bb.setTypeface(type);
   
   holder.product_bbvalue.setText(tempProduct.getProductBBPrice());
   holder.product_bbvalue.setTypeface(type);
   
      return convertView;
 }
 
  static class ViewHolder 
  {         
         TextView product_name;
         TextView product_mrp;
         TextView product_mrpvalue;
         TextView product_bb;
         TextView product_bbvalue;
         TextView product_savings;
         TextView product_savingsvalue;
         TextView qty;
         TextView product_value;
         Button addToCart;
         
         
  }
  
  
  
}

 


Download this zip file and place the contents in the /libs folder of your project.

Download zbar zip file


4 comments:

  1. can you provide the source code in a rar or zip file

    ReplyDelete
    Replies
    1. Source code can be found here

      http://semycolon.blogspot.in/2015/03/source-code-e-commerce-app.html

      Delete
  2. You have never used some tables. for example PRODUCT_MASTER. where they are supposed to be use?

    ReplyDelete
  3. You can visit this post for the source code

    http://semycolon.blogspot.in/2015/03/source-code-e-commerce-app.html

    ReplyDelete