Generate PDF File in Android using Jetpack Compose
There are many apps in which data from the app is provided to users in the downloadable PDF file format. So in this case we have to create a PDF file from the data present inside our app and represent that data properly inside our app. So by using this technique we can easily create a new PDF according to our requirements.
In this article, we will take a look at creating a new PDF file from the data present within our android application using Jetpack Compose in Android.
Steps to Generate PDF File in Android
Step 1: Create a New Project in Android Studio
To create a new project in the Android Studio, please refer to How to Create a new Project in Android Studio with Jetpack Compose.
Step 2: Adding images to the drawable folder
- Copy the image which you want to add to your PDF file.
- Navigate to app>res>drawable.
- Right-click on it and paste all the images into the drawable folder.
Step 3: Adding permissions in AndroidManifest.xml
Navigate to app > manifests > AndroidManifest.xml and add the below permission to it for writing in the external storage (for until Android 9 only).
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
Step 4: Working with the MainActivity.kt file
Go to the MainActivity.kt file and refer to the following code. Below is the code for the MainActivity.kt file. Comments are added inside the code to understand the code in more detail.
MainActivity.kt:
package com.geeksforgeeks.demo
import android.Manifest
import android.content.Context
import android.graphics.*
import android.graphics.pdf.PdfDocument
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.*
import com.geeksforgeeks.demo.ui.theme.DemoTheme
import java.io.File
import java.io.FileOutputStream
class MainActivity : ComponentActivity() {
// Launcher for handling permission requests
private val requestPermissionsLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val granted = permissions.entries.all { it.value }
if (granted) {
Toast.makeText(this, "Permissions Granted.", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Permission Denied.", Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Check and request required permissions
checkAndRequestPermissions()
// Set the Jetpack Compose UI
setContent {
DemoTheme(dynamicColor = false, darkTheme = false) {
Surface(color = Color.White) {
// Display the UI component
PdfGenerator()
}
}
}
}
// Function to check and request
// necessary permissions
private fun checkAndRequestPermissions() {
val requiredPermissions = mutableListOf<String>()
// Request WRITE_EXTERNAL_STORAGE only
// for Android 9 and below
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.Q) {
requiredPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
// Request permissions if any are needed
if (requiredPermissions.isNotEmpty()) {
requestPermissionsLauncher.launch(requiredPermissions.toTypedArray())
}
}
}
@Composable
fun PdfGenerator() {
val context = LocalContext.current
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
// Title text
Text(
text = "PDF Generator",
color = Color.Black,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
fontSize = 20.sp
)
Spacer(modifier = Modifier.height(40.dp))
// Button to generate the PDF
Button(
modifier = Modifier
.fillMaxWidth()
.padding(20.dp),
onClick = { generatePDF(context) }
) {
Text(modifier = Modifier.padding(6.dp), text = "Generate PDF")
}
}
}
// Function to generate a simple PDF document
fun generatePDF(context: Context) {
// Define the page height
val pageHeight = 1120
// Define the page width
val pageWidth = 792
// Create a new PDF document
val pdfDocument = PdfDocument()
// Paint object for drawing
val paint = Paint()
// Paint object for text
val title = Paint()
// Load an image from resources
// (ensure R.drawable.gfg_logo exists)
val bmp: Bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.gfg_logo)
// Resize the image
val scaledBitmap = Bitmap.createScaledBitmap(bmp, 140, 140, false)
// Create a PDF page with specified width and height
val myPageInfo = PdfDocument.PageInfo.Builder(pageWidth, pageHeight, 1).create()
val myPage = pdfDocument.startPage(myPageInfo)
// Get the canvas to draw on
val canvas: Canvas = myPage.canvas
// Draw the image onto the PDF
canvas.drawBitmap(scaledBitmap, 56F, 40F, paint)
// Configure text properties
title.apply {
typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)
textSize = 16F
color = Color.Black.toArgb()
}
// Draw text onto the PDF
canvas.drawText("A portal for IT professionals.", 209F, 120F, title)
canvas.drawText("Geeks for Geeks", 209F, 100F, title)
title.textAlign = Paint.Align.CENTER
canvas.drawText("This is a sample document which we have created.", 396F, 560F, title)
// Finish writing to the page
pdfDocument.finishPage(myPage)
// Define a file path in the app's
// private storage (no permissions required)
val file = File(context.getExternalFilesDir(null), "GFG.pdf")
try {
// Write the PDF to the file
pdfDocument.writeTo(FileOutputStream(file))
Toast.makeText(context, "PDF saved at ${file.absolutePath}", Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(context, "Failed to generate PDF", Toast.LENGTH_SHORT).show()
}
// Close the document
pdfDocument.close()
}