Android generate PDF using iText and print to Bluetooth printer example

In this example we are trying to achieve two things, first and foremost how to create a PDF programmtically from your android application data and second print it using a bluetooth printer so that we don't have to rely on internet connectivity. For the purpose of generating a PDF this tutorial is using iText for Android which is a licensed version of iText with reduced file size and functionality that works on Android. There is another library called droidText which is port of iText for Android. Here are the links for both iText and droidText.
You can play around with both and see if droidText can work for you. iText for Android provides you with a 30 day trial license, just use the link here http://demo.itextsupport.com/newslicense/

Now for the purpose of printing to a bluetooth printer this application uses PrintShare Premium Key app which is also a licensed product. Here is the link for the google play store
https://play.google.com/store/apps/details?id=com.dynamixsoftware.printershare.premium

(Please Note: This is not a recommendation to use the above mentioned product, you can find another app on the play store or write to the bluetooth printer directly)

If you get the error Could not find class 'org.spongycastle.cert.X509CertificateHolder' during run time then you must include the following libraries from the spongycastle github project, here is the link https://github.com/rtyley/spongycastle-eclipse/tree/master/libs
  • sc-light-jdk15on-1.47.0.2.jar
  • scpkix-jdk15on-1.47.0.2.jar
  • scprov-jdk15on-1.47.0.2.jar
Android PDF using iText Android generate PDF using iText and print to Bluetooth printer Android PDF external storage in DDMSAndroid generate PDF

Screen Layout - 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" tools:context=".MainActivity"
 android:padding="5dp">

 <TextView android:id="@+id/textView1" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentLeft="true"
  android:layout_alignParentTop="true" android:text="Enter you name and hit PRINT"
  android:textAppearance="?android:attr/textAppearanceMedium" />

 <EditText android:id="@+id/preparedBy" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView1"
  android:layout_below="@+id/textView1" android:ems="10"
  android:inputType="textPersonName">

  <requestFocus />
 </EditText>

 <Button android:id="@+id/printPDF" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignRight="@+id/preparedBy"
  android:layout_below="@+id/preparedBy" android:layout_marginTop="10dp"
  android:text="Print PDF" android:onClick="printPDF" />

</RelativeLayout>

Activity source - MainActivity.java

package com.as400samplecode;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;

import com.itextpdf.license.LicenseKey;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends Activity {

 private static final String LOG_TAG = "GeneratePDF";

 private EditText preparedBy;
 private File pdfFile;
 private String filename = "Sample.pdf";
 private String filepath = "MyInvoices";

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

  //get reference to the edittext so pull data out
  preparedBy = (EditText) findViewById(R.id.preparedBy);
  //need to load license from the raw resources for iText
  //skip this if you are going to use droidText
  InputStream license = this.getResources().openRawResource(R.raw.itextkey);
  LicenseKey.loadLicenseFile(license);

  //check if external storage is available so that we can dump our PDF file there
  if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) {  
   Log.v(LOG_TAG, "External Storage not available or you don't have permission to write");
  } 
  else {
   //path for the PDF file in the external storage
   pdfFile = new File(getExternalFilesDir(filepath), filename);
  }

 }

 public void printPDF(View v) {

  switch (v.getId()) {

  //start the process of creating the PDF and then print it
  case R.id.printPDF:
   String personName = preparedBy.getText().toString();
   generatePDF(personName);
   break;

  }

 }

 private void generatePDF(String personName){

  //create a new document
  Document document = new Document();

  try {
   
   PdfWriter docWriter = PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
   document.open();

   
   PdfContentByte cb = docWriter.getDirectContent();
   //initialize fonts for text printing
   initializeFonts();

   //the company logo is stored in the assets which is read only
   //get the logo and print on the document
   InputStream inputStream = getAssets().open("olympic_logo.png");
   Bitmap bmp = BitmapFactory.decodeStream(inputStream);
   ByteArrayOutputStream stream = new ByteArrayOutputStream();
   bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
   Image companyLogo = Image.getInstance(stream.toByteArray());
   companyLogo.setAbsolutePosition(25,700);
   companyLogo.scalePercent(25);
   document.add(companyLogo); 

   //creating a sample invoice with some customer data
   createHeadings(cb,400,780,"Company Name");
   createHeadings(cb,400,765,"Address Line 1");
   createHeadings(cb,400,750,"Address Line 2");
   createHeadings(cb,400,735,"City, State - ZipCode");
   createHeadings(cb,400,720,"Country");

   //list all the products sold to the customer
   float[] columnWidths = {1.5f, 2f, 5f, 2f,2f};
   //create PDF table with the given widths
   PdfPTable table = new PdfPTable(columnWidths);
   // set table width a percentage of the page width
   table.setTotalWidth(500f);

   PdfPCell cell = new PdfPCell(new Phrase("Qty"));
   cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
   table.addCell(cell);
   cell = new PdfPCell(new Phrase("Item Number"));
   cell.setHorizontalAlignment(Element.ALIGN_LEFT);
   table.addCell(cell);
   cell = new PdfPCell(new Phrase("Item Description"));
   cell.setHorizontalAlignment(Element.ALIGN_LEFT);
   table.addCell(cell);
   cell = new PdfPCell(new Phrase("Price"));
   cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
   table.addCell(cell);
   cell = new PdfPCell(new Phrase("Ext Price"));
   cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
   table.addCell(cell);
   table.setHeaderRows(1);

   DecimalFormat df = new DecimalFormat("0.00");
   for(int i=0; i < 15; i++ ){
    double price = Double.valueOf(df.format(Math.random() * 10));
    double extPrice = price * (i+1) ;
    table.addCell(String.valueOf(i+1));
    table.addCell("ITEM" + String.valueOf(i+1));
    table.addCell("Product Description - SIZE " + String.valueOf(i+1));
    table.addCell(df.format(price));
    table.addCell(df.format(extPrice));
   }

   //absolute location to print the PDF table from 
   table.writeSelectedRows(0, -1, document.leftMargin(), 650, docWriter.getDirectContent());
   
   //print the signature image along with the persons name
   inputStream = getAssets().open("signature.png");
   bmp = BitmapFactory.decodeStream(inputStream);
   stream = new ByteArrayOutputStream();
   bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
   Image signature = Image.getInstance(stream.toByteArray());
   signature.setAbsolutePosition(400f, 150f);
   signature.scalePercent(25f);
   document.add(signature); 

   createHeadings(cb,450,135,personName);
   
   document.close();
  } 
  catch(Exception e){
   e.printStackTrace();
  }

  //PDF file is now ready to be sent to the bluetooth printer using PrintShare
  Intent i = new Intent(Intent.ACTION_VIEW);
  i.setPackage("com.dynamixsoftware.printershare");
  i.setDataAndType(Uri.fromFile(pdfFile),"application/pdf");
  startActivity(i);

 }

 private void createHeadings(PdfContentByte cb, float x, float y, String text){

  cb.beginText();
  cb.setFontAndSize(bfBold, 8);
  cb.setTextMatrix(x,y);
  cb.showText(text.trim());
  cb.endText(); 

 }


 private static boolean isExternalStorageReadOnly() {  
  String extStorageState = Environment.getExternalStorageState();  
  if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {  
   return true;  
  }  
  return false;  
 }  

 private static boolean isExternalStorageAvailable() {  
  String extStorageState = Environment.getExternalStorageState();  
  if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {  
   return true;  
  }  
  return false;  
 }  

 private void initializeFonts(){


  try {
   bfBold = BaseFont.createFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
  
  } catch (DocumentException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }

}

Some examples that may help you in creating PDF and signature capture