ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

PDFViewerFragment — AndroidX

Header Image

In this article, we will explore the new library introduced under AndroidX ☂️ called PdfViewer

The first alpha version of this library was published on August 7, 2024.

Current version is 1.0.0-alpha02

Major limitation : Currently it support only Android V [SDK 35]

It provides us PdfViewerFragment that we can use in our application to show/view the PDF files.

Here is one of the most common solutions used by Android applications 👇

// create intent
val pdfIntent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(pdfUri, "application/pdf")
setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
}

// try to open the intent - If there is any activity that can handle it
try {
startActivity(pdfIntent)
} catch (activityNotFoundException: ActivityNotFoundException) {
Log.e(TAG, "onCreate: ${activityNotFoundException.message}")
}

Implementation

  • We will go through the compose-based implementation

Add dependency

// version catalog
pdf-viewer-fragment = {module = "androidx.pdf:pdf-viewer-fragment", version.ref = "pdfViewerFragment"}

// app level build.gradle
implementation(libs.pdf.viewer.fragment)

Create a launcher for ActivityResult using rememberLauncherForActivityResult

  • We will use built-in ActivityResultContracts.GetContent() to pick a pdf file 🗒️
var pdfURI: Uri? by remember { mutableStateOf(null) }

val pickFileLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
if(uri != null) {
pdfURI = uri
}
}

Compose based UI

Column(modifier = Modifier
.safeContentPadding()
.padding(32.dp)) {

ElevatedButton(
onClick = { pickFileLauncher.launch("application/pdf") },
modifier = Modifier.fillMaxWidth()) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Default.Add, contentDescription = null)
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
Text("Pick PDF")
}
}

// Show PdfFragment when pdfURI is not null
pdfURI?.let {
AndroidViewBinding(
factory = PdfFragmentViewBinding::inflate,
modifier = Modifier
.padding(horizontal = 16.dp)
) {
val fragment = fragmentContainerPdfViewer.getFragment<PdfViewerFragment>()
fragment.documentUri = uriI
}

}

}
  • On button’s click, we launch the pickFileLauncher, and update the pdfURI based on the result
Initial UI state
var pdfURI: Uri? by remember { mutableStateOf(null) }
  • pdfURI is mutableState so whenever it gets changed it automatically updates the documentUri property of the fragment
pdfURI?.let {
AndroidViewBinding(
factory = PdfFragmentViewBinding::inflate,
modifier = Modifier
.padding(horizontal = 16.dp)
) {
val fragment = fragmentContainerPdfViewer.getFragment<PdfViewerFragment>()
fragment.documentUri = uriI
}

}

We can also use the new Composable introduced in fragment version 1.8.0 called AndroidFragment

  • Currently, PdfViewerFragment is not working with this composable due to API limitations, but hopefully, these issues will be resolved in future releases.
pdfURI?.let {
Log.d(TAG, "Selected URI: $pdfURI")
AndroidFragment<PdfViewerFragment>(
arguments = bundleOf("documentUri" to pdfURI),
modifier = Modifier.fillMaxSize()
) { pdfViewerFragment ->
Log.d(TAG, "URI ${pdfViewerFragment.documentUri}")
}

Demo

Demo — PdfViewerFragment

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by Nav Singh

Google Developer Expert for Android | Mobile Software Engineer at Manulife | Organizer at GDG Montreal

Responses (2)

Write a response

For those of you wondering what PdfFragmentViewBinding is - herer is the missing piece:
Just add a file pdf_fragment_view.xml to your xml layouts with the following content:
<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainer…

--

Only SDK 35 ……

--