안드로이드 앱에서 PDF 파일로 출력하는 방법을 정리하여 공유합니다.
여러 블로그를 돌아다녀 봤으나 마음에 드는 방법을 찾을 수 없어 itextpdf.com 에서 제공하는 라이브러리를 사용해보았습니다.
하지만 itext5, 7은 사이트상에서 명기하길 AGPL 라이센스 정책을 따른다고 표기되어있습니다. 따라서 상업용 앱개발을 하시는 분들은 유료로 사용하셔야 할 것 같습니다.
이제 사용법을 알아보겠습니다. 새프로젝트를 하나 만들고, 각각의 파일에 다음과 같이 코드를 추가합니다.
사용법
file : libs.version.toml
[versions] itext7 = "8.0.3" [libraries] itext7-kernel = { group = "com.itextpdf.android", name = "kernel-android", version.ref = "itext7" } itext7-layout = { group = "com.itextpdf.android", name = "layout-android", version.ref = "itext7" }
file : build.gradle.kts (module :app)
implementation(libs.itext7.kernel) implementation(libs.itext7.layout)
file : activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/btn_write_pdf" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Write PDF" /> </LinearLayout>
file : MainActivity.kt
class MainActivity : AppCompatActivity() { private val FILE_TYPE = "FileType" private val FILE_TYPE_PDF = 101 lateinit var btnWritePdf: Button override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContentView(R.layout.activity_main) ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } btnWritePdf = findViewById(R.id.btn_write_pdf) btnWritePdf.setOnClickListener { writePdf() } } private val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { result.data.also { intent -> intent?.data?.also { url -> requestWritePdfData(url) } } } } private fun requestWritePdfData(uri: Uri) { lifecycleScope.launch(Dispatchers.IO) { contentResolver.openFileDescriptor(uri, "w").use { descriptor -> if (descriptor != null) { FileOutputStream(descriptor.fileDescriptor).use { stream -> val writer = PdfWriter(stream) val pdf = PdfDocument(writer) val document = Document(pdf, PageSize.A4) val content = "Hello World!!!" val paragraph = Paragraph(content) paragraph.setFont(PdfFontFactory.createFont(StandardFonts.HELVETICA)) document.setMargins(50f, 50f, 50f, 50f) document.add(paragraph) document.close() } } } } } private fun writePdf() { val fileName = "PdfSample" val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "application/pdf" putExtra(FILE_TYPE, FILE_TYPE_PDF) putExtra(Intent.EXTRA_TITLE, "$fileName.pdf") } launcher.launch(intent) } }
위 코드를 작성 후에 빌드하신 뒤 버튼을 누르면 파일명을 선택하는 화면이 뜹니다.
적절한 파일명 입력한 뒤에 [SAVE] 버튼을 누르면 저장됩니다. 저장된 파일은 Device Explorer로 들어가서 받아와 열어보시면 PDF 파일이 만들어 진 것을 확인할 수 있습니다.