Background
Traditionally, working with PDF on Android has been hard because there is no PDF support built into the OS. To be able to work with PDF across the major Android OS versions in use, you typically have to resort to third-party commercial libraries or online services that can process PDF files remotely. Both approaches have their problems: commercial PDF libraries require thousands of dollars in yearly maintenance while online services introduce significant delays in processing, plus don’t work when Internet is not available.
Recent Developments
Recently, some new options have emerged that make working with PDF on Android much more convenient. A new project called PDFBox-Android brings the power of the well-known Apache PDFBox open-source library to Android. You can now create, alter, merge, split and render PDF documents easily and for free. The main advantages of this solution are:
- Open source license based on Apache 2 that allows you to use the component in commercial applications without onerous license fees
- Pure Java library that does not require separate C/C++ libraries for different architectures
- Large community of Java developers already using this library for the desktop. That means that there are numerous StackOverflow threads and blog posts to help you with common usage scenarios.
The Android OS has also added some PDF functionality in recent versions. In API level 19 Google introduced a new class called PdfDocument to generate PDF documents from native content, and in API level 21 Google added another class called PdfRenderer to allow rendering a PDF document. However, the usefulness of these options is limited because they are not available in older Android versions currently in use.
Filling a PDF Form
In this post we will use PDFBox-Android to fill a PDF form. We will use an AcroForms PDF with pre-defined textbox and checkbox fields. In the next part of this series, we will look at inserting a signature into the PDF.
The actual form we will use in this blog post can be found here. If you want to create your own small forms with AcroForm fields, you can use the free PDFescape online form editor. When working professionally with large forms that have a lot of fields, you should probably use Adobe Acrobat because it has automatic AcroForm field insertion can save you from the drudgery of manually defining AcroForm fields.
Adding PDFBox-Android to your Project
If you are using Gradle and Android Studio, you can simply add the jcenter repository and a reference to PDFBox-Android 1.8.9.0 (latest version as of now), as shown below:
In your project’s build.gradle:
allprojects { repositories { jcenter() } }
In your app’s build.gradle:
dependencies { compile 'org.apache:pdfbox-android:1.8.9.0' }
Filling the AcroForm Fields
To get started, we’ll create a skeleton function called fillPdf that opens a PDF, retrieves the AcroForm, makes changes to fields and then closes and save the changes to another PDF file.
public fillPdf(String inFileName, String outFileName) { try { // Load the document document = PDDocument.load(inFileName); // Get the AcroForm PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog(); PDAcroForm acroForm = docCatalog.getAcroForm(); // TODO: Set fields // Save document document.save(outFileName); // Close document document.close(); } catch (IOException ioe) { ioe.printStackTrace(); } }
We change the fields using the setTextField and setCheckBox functions whose implementation is shown below:
public void setTextField(PDAcroForm acroForm, String textFieldName, String text) { PDFieldTreeNode treeNode = acroForm.getField(textFieldName); if( treeNode != null ) { treeNode.setValue(text); } else { Log.e(TAG, "No text field found with name:" + name); } } public void setCheckBoxField(PDAcroForm acroForm, String checkBoxFieldName, boolean isChecked) { PDFieldTreeNode treeNode = acroForm.getField(checkBoxFieldName); if( treeNode != null && treeNode instanceof PDCheckbox) { if (isChecked) { ((PDCheckBox)treeNode).check(); } else { ((PDCheckBox)treeNode).unCheck(); } } else { Log.e(TAG, "No checkbox field found with name:" + name); } }
Finally, we will need to add the calls to edit the form fields in the fillPdf function, replacing the TODO. The final code for fillPdf is shown below.
public fillPdf(String inFileName, String outFileName) { try { // Load the document document = PDDocument.load(inFileName); // Get the AcroForm PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog(); PDAcroForm acroForm = docCatalog.getAcroForm(); // Set AcroForm fields setTextField(acroForm, "name", "John Doe"); setCheckboxField(acroForm, "male", true); setTextField(acroForm, "address", "123 Broadway"); setTextField(acroForm, "city", "New York"); setTextField(acroForm, "state", "NY"); setTextField(acroForm, "zip", "10001"); // Save document document.save(outFileName); // Close document document.close(); } catch (IOException ioe) { ioe.printStackTrace(); } }
Stay tuned for the next part
In the next part we will look at adding the signature into the PDF document. Until then, let us know of any questions in the comments section.