안드로이드를 공부하려고 간단한 pdf 뷰어를 만들어 보다가 안드로이드에서 제공하는 PdfRenderer 클래스를 발견했다.
https://developer.android.com/reference/android/graphics/pdf/PdfRenderer
android developers에서는 PDF를 렌더링하는 일반적인 방법을 다음과 같이 설명하고 있다.
// new renderer
PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor());
// let us just render all pages
final int pageCount = renderer.getPageCount();
for (int i = 0; i < pageCount; i++) {
Page page = renderer.openPage(i);
// say we render for showing on the screen
page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY);
// do stuff with the bitmap
// close the page
page.close();
}
// close the renderer
renderer.close();
var imageList: MutableList<ImageBitmap> = mutableListOf()
var pdfUri by remember { mutableStateOf<Uri?>(null) }
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/pdf"
}
val requestLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
pdfUri = it.data?.data
}
requestLauncher.launch(intent)
val renderer = context.contentResolver.openFileDescriptor(
pdfUri,
"r"
)?.let { PdfRenderer(it) }
for (i in 0 until renderer.pageCount) {
val page = renderer.openPage(i)
val bitmap =
Bitmap.createBitmap(page.width, page.height, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
imageList.add(bitmap.asImageBitmap())
page.close()
}
renderer.close()
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.pdf.PdfRenderer
import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
@Composable
fun PdfViewer(modifier: Modifier = Modifier) {
var imageList: MutableList<ImageBitmap> = mutableListOf()
var pdfUri by remember { mutableStateOf<Uri?>(null) }
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/pdf"
}
val requestLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
pdfUri = it.data?.data
}
when(pdfUri) {
null -> {
Button(onClick = {
requestLauncher.launch(intent)
}) {
Text(text = "PDF 선택")
}
}
else -> {
pdfLoad(pdfUri!!, imageList, LocalContext.current)
LazyColumn(modifier.fillMaxSize()) {
items(imageList) { page ->
Image(
bitmap = page,
contentDescription = null,
modifier = modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
}
}
}
}
}
fun pdfLoad(pdfUri: Uri, imageList: MutableList<ImageBitmap>, context: Context) {
val renderer = context.contentResolver.openFileDescriptor(
pdfUri,
"r"
)?.let { PdfRenderer(it) }
if (renderer != null) {
for (i in 0 until renderer.pageCount) {
val page = renderer.openPage(i)
val bitmap =
Bitmap.createBitmap(page.width, page.height, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
imageList.add(bitmap.asImageBitmap())
page.close()
}
renderer.close()
}
}
https://github.com/hmooko/SimpleAndroidPdfViewer-JetpackCompose