Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Create and Share data in PDF format

Published? true
FormatLanguage: WikiFormat

Problem:

You want to create a PDF document and save it and/or share it.

Solution:

KitKat (API Level 19) introduces a new PDF API for generating PDF documents. It requires you to handle pagination, so your dreams of writing a one-line word processor may be shattered, but it does give you full control over the document contents.

Discussion:

pwd This example generates a PDF document, creates one page in it, draws the content of one View (a multi-line text field) into the document, and shares it.

		// Create a shiny new (but blank) PDF document in memory
		PdfDocument document = new PdfDocument();

		// crate a page description
		PageInfo pageInfo = new PageInfo.Builder(300, 300, 1).create();

		// create a new page from the PageInfo
		Page page = document.startPage(pageInfo);

		// repaint the user's text into the page
		View content = findViewById(R.id.textArea);
		content.draw(page.getCanvas());

		// do final processing of the page
		document.finishPage(page);

The PageInfo represents the size and number of the page. Note that, as in everything PDF-related, the size is in PostScript(tm) units, not Android units! The PostScript unit, for those who've not worked in PostScript, is defined as 1/72nd of an inch, chosen decades ago, presumably to make a 72-point headline occupy one inch of paper.

At this point we could easily loop adding more pages (each one starting with a PageInfo passed into startPage().

Since we don't have any more pages in our simple example, the next step is to write the document to a file. To save it, open an OutputStream to a file on external storage. In our case we don't need to save it to the "disk" or "external storage", we just need to pass it along via the Share mechanism described in 4383, so we'll "write" to a ByteArrayOutputStream, call toByeArray() on that Stream to get the data, and pass it into the Share Intent.

		os = new ByteArrayOutputStream();
		try {
			document.writeTo(os);
			document.close();
			os.close();
		} catch (IOException e) {
			throw new RuntimeException("Error generating file", e);
		}

		mShareIntent = new Intent();
		mShareIntent.setAction(Intent.ACTION_SEND);
		mShareIntent.setType("application/pdf");
		// Assuming it may go via eMail:
                mShareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
			"Here is a PDF from PdfSend");
		mShareIntent.putExtra(
			getClass().getPackage().getName() + "." + "SendPDF", 
			os.toByteArray());
		startActivity(mShareIntent);

Shortly after we run this code, an Email Compose window should appear, with the PDF as an attachment. (XXX Window appears but the attachement is missing!).

There is, of course, more to the PDF library than shown here. Most notably there is a subclass called PrintedPdfDocument that may be more appropriate for generating PDFs that will be printed.

But really, the most important thing is that you can take any View and draw it into a page of the PDF, so the real power comes from the creativity you put into the View. Pass the main activity View and you have a "Share Screen Shot PDF" mechanism.

See Also:

Recipe 4383 describes the Share mechanism.

The Android documentation is at [1].

Adobe.com has general information on PDF itself, at [2].

Download:

The source code for this project is in the Android Cookbook repository, http://github.com/IanDarwin/Android-Cookbook-Examples/,in the subdirectory PdfShare.