Android iText Pdf Example

This blog post stems from my recent experience building my soon to be released Invoicing app. I waited until the last minute to integrate PDF hoping that there is a magical boolean I can set to true and voila, my deeply nested view will be converted to PDF. I quickly realized that programmatic PDF involves dealing with a set of complex API. Anyone approaching programmatic PDF with the mindset of the ease of GUI PDF is in for a pleasant surprise. As I navigate my way through Pdfland I will be sharing my Android iText PDF example in this and subsequent posts.

In this post I will begin with the basics of how to use the iTextg library to create a PDF document in Android which will make this blog post a basic introduction to iText in Android. Itext is a popular library for creating and manipulating PDF documents. It was originally written for Java but has since been ported to .Net, Android and other platforms. Surprisingly iText for Android (called iTextG) tutorials are often hard to find or the blog or tutorial date seems dated, however I will admit that Stackoverflow has lots of helpful content and helpful pointers regarding iText in Android .

If you plan to do any meaningful work with programmatic PDF you will be well served to make an investment in this book iText in Action by Bruno Lowagie, I am very glad that I did. In this book, the author who is also the creator of the iText library outlined 5 steps to creating PDF with iText.

Steps in Creating a PDF Document with Itext (Excerpt from iText in Action)

Step 1: Create a Document
Step 2: Get a PDFWriter instance
Step 3: Open the Document
Step 4: Add Content
Step 5: Close the Document</>

These steps applies whether you are creating PDF in server, web or mobile environment. Now, let us see how we can apply these steps in an Android app. To do this, lets create a simple application named SelfNote. This app lets you quickly take enter some notes for yourself and either email it to yourself as a PDF or view it. This is a glorified Hello World of PDF in Android with iText. Below is what the final app will look like once complete.

Step 1: Create a Document

Go ahead and create a standard Android Studio project and name it anything you like, I have named mine PdfDemo. In this project, add a Fragment with its own xml layout and name it SelfNoteFragment and the xml fragment_self_note_xml. If you created a new project, you can go ahead and delete the PlaceHolderFragment and any reference to it in the MainActivity. Below is the content of the fragment_self_note.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_margin="@dimen/activity_vertical_margin"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <EditText
        android:id="@+id/edit_text_subject"
        android:hint="@string/hint_subject"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <EditText
        android:id="@+id/edit_text_body"
        android:hint="@string/hint_body"
        android:layout_width="match_parent"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/button_save"
        android:layout_width="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_height="wrap_content"
        android:text="Save"/>

</LinearLayout>

And the Main Activity’s layout activity_main.xml just has a FrameLayout with the Id of container like so:

&lt;FrameLayout
 android:id="@+id/container"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 xmlns:android="http://schemas.android.com/apk/res/android"/&gt;

The Java code in the Main Activity just points to the SelfNoteFragment like below. All the code for creating the PDF will be contained inside the SelfNoteFragment so we can add more Fragments to the project for upcoming Android iText tutorials. Here is the Main Activity onCreate code.

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

        SelfNoteFragment noteFragment = SelfNoteFragment.newInstance();

        android.support.v4.app.FragmentTransaction fragTransaction= this.getSupportFragmentManager().beginTransaction();
        fragTransaction.replace(R.id.container, noteFragment);
        fragTransaction.commit();
    }

Here is the starting Java code for the SelfNoteFragment.

public class SelfNoteFragment extends Fragment {
    private View mRootView;
    private EditText mSubjectEditText, mBodyEditText;
    private Button mSaveButton;

    public SelfNoteFragment() {
        // Required empty public constructor
    }

    public static SelfNoteFragment newInstance(){
        SelfNoteFragment fragment = new SelfNoteFragment();
        return fragment;
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        mRootView = inflater.inflate(R.layout.fragment_self_note, container, false);
        mSubjectEditText = (EditText) mRootView.findViewById(R.id.edit_text_subject);
        mBodyEditText = (EditText) mRootView.findViewById(R.id.edit_text_body);
        mSaveButton = (Button) mRootView.findViewById(R.id.button_save);
        return mRootView;
    }
}

Now unto the PDF world. Create a method called createPdf() in the SelfNoteFragment like this

  private void createPdf(){

    }

Add the iText Library to Android Studio

Click on Project
Project Structure
On the left hand side, under Modules, highlight app
Click on Dependencies tab
Click on the green plus sigh to the far right
Click on Library dependencies
Type itext in the search bar and hit enter
Select the latest version of the iText library for Android as show below
Click Ok and OK, and give Gradle a minute to rebuild


Under your createPdf() method, the first thing we need to do is to create a folder where we will save the PDF files we will be creating and we do this with the code below:

 File pdfFolder = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOCUMENTS), "pdfdemo");
        if (!pdfFolder.exists()) {
            pdfFolder.mkdir();
            Log.i(LOG_TAG, "Pdf Directory created");
        }

Next we need to create the name(s) of the Pdf file we are going to create. We do this my appending the current date and time to the string “SelfNote” and then append “.pdf” like this:

Date date = new Date() ;
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(date);

        File myFile = new File(pdfFolder + timeStamp + ".pdf");

Next create an output stream where the iText library will write the PDF to, and point the output stream to the myfile we created. File operations can through an exception that means that it has some probability of failing therefore, the IDE will prompt you to add an exception to the signature of the method or surround the call to FileOutputStream with a Try/Catch clause. Because of this reason, go ahead and add a FileNotFoundException to the signature of the createPdf() method and with that the method will now look like this:

private void createPdf() throws FileNotFoundException {

        File pdfFolder = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOCUMENTS), "pdfdemo");
        if (!pdfFolder.exists()) {
            pdfFolder.mkdir();
            Log.i(LOG_TAG, "Pdf Directory created");
        }

        //Create time stamp
        Date date = new Date() ;
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(date);

        File myFile = new File(pdfFolder + timeStamp + ".pdf");

        OutputStream output = new FileOutputStream(myFile);

    }

Good progress, we now have a place to write our yet to be created PDF file. Remember I told you, programmatic PDF is not for the faint of heart.

Now the fun begins! Create the PDF with this one line of Code

Document document = new Document();

That easy! – yes. In reality though the iText library did quite a few things for you under the hood. For one it supplied or implied your measurement. This is because PDF does not have an infinite dimension like an Android ScrollView. It has a defined measurements that has to be specified at the time of creation and since we did not specify one the iText library filled in the gaps for us like so:

Rectangle pagesize = new Rectangle(216f, 720f);
Document document = new Document(pagesize, 36f, 72f, 108f, 180f);

The library also provides lots of helper methods and constants that will help you gain granular control of what is created. For example the above document created a standard European sized document, to create an American standard sized document you can create the document instead like this:

Document document = new Document(PageSize.LETTER);

Step 2: Get an Instance of PdfWriter

The PdfWriter class is responsible for writing the PDF file. And in this step, you associate the blank document we created above with the PdfWriter class and point it to the output stream where the PDF will be written to like so:

//Step 2
PdfWriter.getInstance(document, output);

And again we need to add DocumentException to the signature of this method so it looks like this with the content removed for brevity.

private void createPdf() throws FileNotFoundException, DocumentException {}

Step 3: Open the PDF Document

This step could as well has been named Initialization. A PDF is not a PDF until it is opened or initialized. When you call open the document the library performs some low level initialization of the PDF such as adding the file headers, the PDF version, making any bookmarks available, etc

//Step 3
        document.open();

Step 4: Add Content

In this step we add two content (paragraph) corresponding to the two EditTexts in our layout like this:

//Step 4 Add content
        document.add(new Paragraph(mSubjectEditText.getText().toString()));
        document.add(new Paragraph(mBodyEditText.getText().toString()));

And we are done, of course you can guess that more than paragraphs can be added, you can get this book below to get deeper information about all the possibilities with PDF

Step 5: Close the Document

//Step 5: Close the document
document.close();
Let iText know that you are done so it can flush the content to the stream and close the output stream that we opened. The whole method should look like this when you are done.

private void createPdf() throws FileNotFoundException, DocumentException {

        File pdfFolder = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOCUMENTS), "pdfdemo");
        if (!pdfFolder.exists()) {
            pdfFolder.mkdir();
            Log.i(LOG_TAG, "Pdf Directory created");
        }

        //Create time stamp
        Date date = new Date() ;
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(date);

        File myFile = new File(pdfFolder + timeStamp + ".pdf");

        OutputStream output = new FileOutputStream(myFile);

        //Step 1
        Document document = new Document();

        //Step 2
        PdfWriter.getInstance(document, output);

        //Step 3
        document.open();

        //Step 4 Add content
        document.add(new Paragraph(mSubjectEditText.getText().toString()));
        document.add(new Paragraph(mBodyEditText.getText().toString()));

        //Step 5: Close the document
        document.close();

    }

Viewing PDF in Android

And that is it we are done with creating a PDF document with Android with iTextG. How about reading it. That is very simple, we will not recreate the wheel, just throw up an Intent and let Adobe Viewer of any other installed PDF viewer view the document like this:

private void viewPdf(){
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(myFile), "application/pdf");
        intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
        startActivity(intent);
    }

Email PDF Attachment in Android

Sending an email with a PDF attachment is equally easy, just like with viewing it on the screen, we show an Intent that uses an email client such as Gmail to send the email like this:

private void emailNote()
    {
        Intent email = new Intent(Intent.ACTION_SEND);
        email.putExtra(Intent.EXTRA_SUBJECT,mSubjectEditText.getText().toString());
        email.putExtra(Intent.EXTRA_TEXT, mBodyEditText.getText().toString());
        Uri uri = Uri.parse(myFile.getAbsolutePath());
        email.putExtra(Intent.EXTRA_STREAM, uri);
        email.setType("message/rfc822");
        startActivity(email);
    }

To give an option of either sending the the PDF as email or just vieweing on the screen, we add a dialog prompt which is called at the end of the PDF document creation. Here is the method that shows the dialog with an option to either view the PDF document or send an email attachment with the PDF document:

private void promptForNextAction()
    {
        final String[] options = { getString(R.string.label_email), getString(R.string.label_preview),
                getString(R.string.label_cancel) };

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("Note Saved, What Next?");
        builder.setItems(options, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (options[which].equals(getString(R.string.label_email))){
                    emailNote();
                }else if (options[which].equals(getString(R.string.label_preview))){
                    viewPdf();
                }else if (options[which].equals(getString(R.string.label_cancel))){
                    dialog.dismiss();
                }
            }
        });

        builder.show();

    }

Update the createPdf() method to call the promptForNextAction() method right after document.close(). Finally add an onlick listener to the Save button that calls the createPdf() and check for null in the EditTexts so we do not create blank documents. Also add try/catch blocks to catch the Exceptions that we added to the createPdf() signature like this:

mSaveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mSubjectEditText.getText().toString().isEmpty()){
                    mSubjectEditText.setError("Subject is empty");
                    mSubjectEditText.requestFocus();
                    return;
                }

                if (mBodyEditText.getText().toString().isEmpty()){
                    mBodyEditText.setError("Body is empty");
                    mBodyEditText.requestFocus();
                    return;
                }

                try {
                    createPdf();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (DocumentException e) {
                    e.printStackTrace();
                }
            }
        });

Thanks for reading and goodluck with your Pdf adventures.

About the Author valokafor

I am a Software Engineer with expertise in Android Development. I am available for Android development projects.

follow me on:

Leave a Comment: