Developing an Android PDF reader with annotations
A good PDF reader should do more than scroll pages. It should let a user highlight a clause, sketch over a floor plan, or pin a note beside a diagram, then keep those changes after the app closes. For Australian users, a PDF reader with annotations should feel immediate, work offline and handle large documents without drama.
That need is practical: commuters in Sydney and Melbourne read reports on trains, while students and tradies in Brisbane and regional Queensland review papers and mark installation guides. A poor signal should not erase someone’s work, so local files and dependable autosave matter. Field crews around Perth and Darwin also need annotations to survive an offline afternoon. The informal “no worries” expectation is genuine: the app should recover gracefully rather than nag.
The central design choice is to separate the document from the marks made on it. Android’s PdfRenderer can display pages but does not provide editable PDF objects or text selection. Most native apps therefore render page images, capture gestures in an overlay, and store annotations in a database before offering export or synchronisation.
Choose the rendering approach
Choose the rendering approach first because it shapes text selection, gesture handling and export. The native framework gives you complete control over an overlay, while browser-based and commercial engines provide document features that take years to reproduce.
| Approach | Capability | Annotation work | Best fit |
|---|---|---|---|
Android PdfRenderer |
Pages as bitmaps without text selection | Custom canvas and database | Small, controlled native reader |
| Bundled PDF.js | Pages, selectable text and search | JavaScript bridge and coordinate mapping | Offline reader with searchable text |
| Commercial PDF SDK | Pages, text, forms and signatures | Built-in annotation APIs | Enterprise features under licence |
For a focused native reader, PdfRenderer plus an overlay is usually the simplest foundation. Choose PDF.js when searchable text matters and your team can manage a WebView bridge. A commercial SDK is attractive when signing, forms or collaboration must ship quickly, but compare licence costs and Android build support before committing. For the native path, create an Android Studio project with minimum API 21, add Room and lifecycle dependencies, and use ACTION_OPEN_DOCUMENT to select a file.
Store annotations outside the PDF
Treat every mark as app-owned data rather than an immediate edit inside the PDF. PdfRenderer is read-only, so highlights, ink and notes need a home that can outlive the rendered bitmap. Room, Android’s SQLite abstraction, suits structured records; SharedPreferences is suitable only for lightweight preferences such as the last open page, zoom level or selected tool.
@Entity(tableName = "annotations")
data class AnnotationEntity(
@PrimaryKey val id: String,
val documentUri: String,
val pageIndex: Int,
val type: String,
val payload: String,
val updatedAt: Long
)
Save points as ratios of page width and height, not device pixels. A normalised value such as 0.42 remains aligned after zooming, rotating or opening the document on a tablet with another aspect ratio. Give each annotation a generated ID, record its page index and store text or path data as JSON. Upsert records after each completed gesture, and keep undo history in memory until the current action is safely committed.
Design the reader around pages and gestures
Build page navigation with a RecyclerView of lazily generated thumbnails, then show the selected page in a zoomable custom View. Render off the main thread and close each PdfRenderer.Page after producing a bitmap. Reuse decoded images, cap bitmap sizes and load neighbouring pages only when needed; a 500-page manual should not consume hundreds of megabytes.
Let the canvas transform drive both page display and annotation drawing. When the user pinches or pans, apply the same matrix to the bitmap and overlay coordinates. Add a visible page indicator, thumbnail drawer and obvious controls for fit-width, rotation and tool selection. Save the viewer matrix in saved instance state so rotation does not send the reader back to page one.
Implement drawing, highlighting and notes
Implement each annotation mode as a separate state: freehand ink, rectangular highlight, text note and eraser. Store sampled points with timestamps, honour stylus pressure where available, and let Undo remove the last committed object. Drawing and scrolling must not compete for the same gesture, so activate inking only after the user chooses a tool and make that mode clear on screen.
Text highlighting needs extra care because PdfRenderer exposes pixels rather than character positions. Either restrict the first release to freehand marks and notes, or add a text engine and map its glyph boxes into page coordinates. Test alignment at different zoom levels, and never imply selectable text exists when the renderer only supplies an image. Colour choices should also remain distinguishable for common colour-vision deficiencies.
Recommendations for dependable annotation handling
A dependable workflow should protect work before it tries to add sophisticated features. Follow these practices while building the annotation layer:
- Open documents through Android’s Storage Access Framework and persist URI permission; handle access being revoked or the file being replaced.
- Keep page coordinates normalised, use stable annotation IDs and autosave to Room after every completed action.
- Make the active tool obvious, support Undo and Redo, and separate drawing gestures from page navigation.
- Test offline mode, rotation, process death, low memory, cancelled imports and reopening a document on another device.
- Define export rules early: keep a portable sidecar file or use a library capable of writing an annotated PDF.
For a manageable first release, deliver page viewing, zoom, freehand ink, highlights and notes with a JSON sidecar export. True PDF writing, collaborative links and cloud sync can follow once the annotation model and coordinate system prove stable across Android versions.
Test, protect and publish the app
Exercise the reader on physical phones and tablets with current and older supported Android releases. Include large scanned documents, low-memory devices, stylus input, TalkBack labels and Australian English spellings. Check that process death does not lose an unsaved mark, that a cancelled document selection leaves the previous file intact and that exporting produces a file another reader can open.
Local files can reduce permission requirements, but annotations may contain names, signatures or medical details. Australian organisations using the app should assess the Privacy Act 1988 and Australian Privacy Principles, especially if notes are uploaded for synchronisation. Encrypt sensitive local data, avoid logging annotation contents and disclose retention practices. For Google Play, complete the Data Safety form, explain account deletion when applicable, and price subscriptions in AUD with Australian GST handled correctly.
A polished offline reader with durable marks gives Australian users a practical tool for commutes, study and fieldwork without making them trade privacy for convenience.