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
Job Offers
var pdfURI: Uri? by remember { mutableStateOf(null) }
pdfURI is
mutableState so whenever it gets changed it automatically updates the
documentUri
property of thefragment
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
Stay in touch 🤝
https://www.linkedin.com/in/navczydev/
https://twitter.com/navczydev?source=post_page—–b31cd5398ac4——————————–
https://github.com/navczydev?source=post_page—–b31cd5398ac4——————————–
References
This article is previously published on proandroiddev.com