Integrate zxing barcode scanner into your Android app natively using Eclipse

June 13, 2011

Edit: Sean Owen, one of the developers for ZXing has posted a comment to this blog warning of the pitfalls of integrating ZXing into your own app; doing so just to avoid having your users take that extra step of installing from the market is not a good reason. I completely agree with this. There are many advantages to using the intent based approach as outlined in his comments. My motivation is for an enterprise app that does not have access to the Android market and involves my client installing zxing manually on thousands of devices before they are able to distribute to its business customers.

So to be clear, do not use this method unless it is absolutely necessary, and if you do have to – make sure that override your intent filters so that other apps that want to use zxing do not end up calling your modified version. Also, if zxing is already installed, then you should use that by default instead of your modified version.

ZXing is one of the most popular barcode scanning applications on the market. They make it very easy for you to integrate into your application via an intent but this means that your users must manually install the application from the market.

Fortunately, the app is also open source so I will show you how to cleanly build this capability into your project.

Please note that the awesome developers of this product have released the src under the Apache v2.o license so please be sure to adhere to the terms of this license and give them full credit for their work. http://www.apache.org/licenses/LICENSE-2.0

Step One: Obtain the zxing src code
The src can be found at http://code.google.com/p/zxing/source/browse/trunk. Specifically you only need the android/ and the core/ projects. Use svn to checkout these to your local hard-drive.

Step Two: Build zxing core using Apache Ant
You will need to build the core project into a jar file using apache ant (download from herehttp://ant.apache.org/ivy/download.cgi). Using a shell or cmd prompt navigate to the root directory of the downloaded zxing src and execute ”ant -f core/build.xml”. This will produce a file core/core.jar which we will use in the next step.

Step Three: Build ZXing Android using Eclipse
Create a New Android Project (File –> New –> Android Project).
Set the project name to ZXing (or similar).
Select the “Create project from existing source” radio button
Click “Browse” and navigate to the android project that you downloaded from zxing and click “OK”
Select “Finish”

The project will not currently build. We need to add the core.jar file (that we produced in the previous step) into our project. Right-click on ZXing project –> properties –> Java Build Path –> Add External Jars –> Navigate to and select core.jar –> Open –> OK.

Actually, while we’re here we should do one more very important thing! Right-click on ZXing project –> properties –> Android –> Scroll down and check/tick the “Is Library” checkbox –> OK.

Step 4: Include ZXing Android into your project.
Within Eclipse,  Right-click on YOURPROJECTNAMEHERE project –> properties –>Android –> Scroll down to Libraries section –> Click Add –> Select ZXing (which should appear as an option as a result of completing previous step).

Next, in some trigger function e.g. button press within your code you should add:

 

1 Intent intent = new Intent("com.google.zxing.client.android.SCAN");
2 intent.putExtra("SCAN_MODE""QR_CODE_MODE");
3 startActivityForResult(intent, 0);

 

In the same activity you’ll need the following to retrieve the results:

 

01 public void onActivityResult(int requestCode, int resultCode, Intent intent) {
02    if (requestCode == 0) {
03       if (resultCode == RESULT_OK) {
04          String contents = intent.getStringExtra("SCAN_RESULT");
05          String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
06          // Handle successful scan
07       else if (resultCode == RESULT_CANCELED) {
08          // Handle cancel
09       }
10    }
11 }

 

Almost there! One of the current limitations of Android Library projects is that it will not pull anything from AndroidManifest.xml into your project.
So if we try to invoke the above code we will receive a runtime exception because your Android app has no idea how to handle the scan intent.
To fix this you just need to copy the following into your AndroidManifest.xml:

 

01 <activity android:name="com.google.zxing.client.android.CaptureActivity"
02    android:screenOrientation="landscape"
03    android:configChanges="orientation|keyboardHidden"
04    android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
05    android:windowSoftInputMode="stateAlwaysHidden">
06    <intent-filter>
07       <action android:name="android.intent.action.MAIN"/>
08       <category android:name="android.intent.category.DEFAULT"/>
09    </intent-filter>
10    <intent-filter>
11       <action android:name="com.google.zxing.client.android.SCAN"/>
12       <category android:name="android.intent.category.DEFAULT"/>
13     </intent-filter>
14 </activity>

 

And as Columbo would say, “Just one more thing!”. Add this permission to the top of your AndroidManifest.xml:

 

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

 

EDIT: You need to do yet one more thing! You need to add the core.jar (produced in Step two) to your new project (Right-click your project –> Properties –> Java Build Path –> Add External JARS… –> Select core.jar –> OK). Thanks to Marco and Markosys in the comments for spotting and pointing out the omission!

 

Referenced by: http://damianflannery.wordpress.com/2011/06/13/integrate-zxing-barcode-scanner-into-your-android-app-natively-using-eclipse/#comment-298

http://as400samplecode.blogspot.com/2011/09/android-barcode-scanner-using-zxing.html

Java : BIRT Report Printing Without User Interaction (Background Printing)

May 18, 2009 by laukik81

During one of my projects , I needed server side printing of BIRT report in which User Interaction was not required ie Background Printing. By the term “No User Interaction” , Print Dialog is not involved anywhere. It could be used for batch printing.
Or A copy of viewed report is printed on the server without letting the user to know it.

BIRT provides server side printing but again it comes to User Interaction.Here BIRT’s ReportEngine API Plays a important role.

Steps :

(1). Create a servlet which can be invoked from a simple Java Program or any stored procedure.

(2).In this servlet, run the report through ReportEngine API and generate a temp pdf of report

(3). Print this generated pdf through Java and delete it.

ReportPrintingServlet.java


import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.PrinterJob;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Enumeration;
import java.util.Properties;

import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.birt.core.framework.IPlatformContext;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.core.framework.PlatformFileContext;
import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.EngineConstants;
import org.eclipse.birt.report.engine.api.EngineException;
import org.eclipse.birt.report.engine.api.IReportEngine;
import org.eclipse.birt.report.engine.api.IReportEngineFactory;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.engine.api.PDFRenderOption;

import com.sun.pdfview.PDFFile;

public class ReportPrintingServlet extends HttpServlet{

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

System.out.println("Came for printing");
ServletContext servletContext = getServletConfig().getServletContext();
Object attribute = servletContext.getAttribute("reportprintproperties");
Properties properties = (Properties) attribute;
try
{
generatePDFFile(properties, request);
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void generatePDFFile(Properties properties,HttpServletRequest request) throws Exception
{
final String REPORT_ENGINE = Path of your ReportEngine
final String REPORTS_PATH = Path where .rptdesign files are kept
final String OUTPUT_LOCATION = Location where pdf is to be generated

PDFRenderOption options = new PDFRenderOption();
EngineConfig config = new EngineConfig();
config.setEngineHome(REPORT_ENGINE);
IPlatformContext context = new PlatformFileContext();
config.setEngineContext(context);
IReportEngineFactory factory = (IReportEngineFactory) Platform
.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);

IReportEngine engine = factory.createReportEngine(config);
IReportRunnable runnable = null;
try {
runnable = engine.openReportDesign(REPORTS_PATH);
} catch (EngineException e) {
System.err.println("Design " + REPORTS_PATH + " not found!");
e.printStackTrace();
engine.destroy();
}

IRunAndRenderTask task = engine.createRunAndRenderTask(runnable);

ByteArrayOutputStream fso = new ByteArrayOutputStream();
options.setOutputStream(fso);
options.setOutputFormat(PDFRenderOption.OUTPUT_FORMAT_PDF);
options.setSupportedImageFormats("PNG");
options.setOutputFileName(OUTPUT_LOCATION); //
task.setRenderOption(options);

Enumeration names = request.getParameterNames();

while (names.hasMoreElements()) {
String name = (String) names.nextElement();
String value = request.getParameter(name);
task.setParameterValue(name, value);
}

task.getAppContext().put(EngineConstants.APPCONTEXT_CLASSLOADER_KEY,Thread.currentThread().getContextClassLoader());
task.run();
System.out.println("Created Report " + OUTPUT_LOCATION + ".");
engine.destroy();

String printerName = request.getParameter("printer");
if(printPDF(OUTPUT_LOCATION,printerName))
{
deletePDFFile(OUTPUT_LOCATION);

}
}

private boolean printPDF(String filename,String printerName) throws Exception{

FileInputStream fis = null;
BufferedInputStream bufferedInputStream = null;
ByteBuffer bb = null;

try {
File f = new File(filename);
fis = new FileInputStream(f);
//FileChannel fc = fis.getChannel();
//ByteBuffer bb = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());
bufferedInputStream = new BufferedInputStream(fis);
byte bytes[] = new byte[fis.available()];
bufferedInputStream.read(bytes);
bb = ByteBuffer.wrap(bytes);
PDFFile pdfFile = new PDFFile(bb); // Create PDF Print Page
PDFPrintPage pages = new PDFPrintPage(pdfFile);

// Create Print Job
PrinterJob pjob = PrinterJob.getPrinterJob();
PageFormat pf = PrinterJob.getPrinterJob().defaultPage();
pjob.setJobName(f.getName());

/**
* Use the printer which comes as parameter from URL.
* So that we can redirect the print at runtime to any of the printer.
*/
PrintService selectedPrinter = null;
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
for (PrintService printService : services) {

System.out.println(printService.getName()+" = "+printerName);
if(printService.getName().equalsIgnoreCase(printerName))
{
selectedPrinter = printService;

break;
}

}
pjob.setPrintService(selectedPrinter);

Book book = new Book();
book.append(pages, pf, pdfFile.getNumPages());
pjob.setPageable(book);
System.out.println("Printer : " + pjob.getPrintService().getName());
// Send print job to default printer

pjob.print();
System.out.println("Sent for Printing : ....");

return true;

} catch (Exception e) {
e.printStackTrace();
return false;
}
finally{

bb.clear();
try
{
fis.close();
bufferedInputStream.close();
}
catch(Exception e)
{
throw new Exception(e);
}
finally
{
fis = null;
bufferedInputStream = null;
}

}

}

private void deletePDFFile(String OUTPUT_LOCATION) throws Exception
{

File file = new File(OUTPUT_LOCATION);
boolean deleted = false;
if(file != null &amp;&amp; file.exists())
{
// file.renameTo(new File(OUTPUT_LOCATION.replace(".", "_")));
deleted = file.delete();
}
System.out.println(" Generated PDF Deleted "+deleted);
}

}

Sample URL :

http://infotraksrv:8080/BirtReportPrinting/print?__report=reports/myreport.rptdesign&printer=printserverprinter_name

In above URL,

print : Is the ReportPrintingServet
printer : Parameter specifies the printer location.
__report : Parameter specifies which report is to be printed

PDFRenderer needs to be in your classpath for printing PDF files.
You can download it from here

Note

Loading Report Engine is costly task so it is recommended to have it one time only.

Referenced by: http://laukik.wordpress.com/2009/05/18/java-birt-report-printing-without-user-interaction/