当前位置: 首页 > news >正文

Android PDFBox 的使用指南

Android PDFBox 使用指南

概述

PDFBox是一个强大的PDF处理库,在Android平台上也有对应的实现。本指南将介绍如何在Android项目中使用PDFBox进行PDF文件的加载、读取、修改等操作。

依赖配置

app/build.gradle 中添加PDFBox依赖:

dependencies {implementation 'com.tom-roush:pdfbox-android:2.0.27.0'
}

核心功能

1. 初始化PDFBox

在使用PDFBox之前,必须先初始化资源加载器:

// 在Application或Activity的onCreate中调用
PDFBoxResourceLoader.init(context)

2. 加载PDF文件

从Assets文件夹加载
fun loadPdfFromAssets(context: Context, fileName: String): PDDocument? {return try {context.assets.open(fileName).use { inputStream ->PDDocument.load(inputStream, MemoryUsageSetting.setupMixed(1000 * 1024 * 1024))}} catch (e: IOException) {null}
}
从文件路径加载
fun loadPdfFromFile(filePath: String): PDDocument? {return try {PDDocument.load(File(filePath), MemoryUsageSetting.setupMixed(1000 * 1024 * 1024))} catch (e: IOException) {null}
}

3. 获取PDF信息

fun getPdfInfo(document: PDDocument): String {val info = StringBuilder()// 获取页面数量val pageCount = document.numberOfPagesinfo.append("页面数量: $pageCount\n")// 获取文档信息val documentInformation = document.documentInformationif (documentInformation != null) {info.append("标题: ${documentInformation.title ?: ""}\n")info.append("作者: ${documentInformation.author ?: ""}\n")info.append("主题: ${documentInformation.subject ?: ""}\n")info.append("创建者: ${documentInformation.creator ?: ""}\n")info.append("创建日期: ${documentInformation.creationDate ?: ""}\n")info.append("修改日期: ${documentInformation.modificationDate ?: ""}\n")}return info.toString()
}

4. 提取文本内容

提取整个文档的文本
fun extractText(document: PDDocument): String {return try {val stripper = PDFTextStripper()stripper.text = document} catch (e: IOException) {"提取文本失败"}
}
提取指定页面的文本
fun extractTextFromPage(document: PDDocument, pageIndex: Int): String {return try {val stripper = PDFTextStripper()stripper.startPage = pageIndex + 1stripper.endPage = pageIndex + 1stripper.text = document} catch (e: IOException) {"提取页面文本失败"}
}

5. 获取页面信息

fun getPageInfo(document: PDDocument, pageIndex: Int): String {return try {val page = document.getPage(pageIndex)val mediaBox = page.mediaBoxval cropBox = page.cropBox"页面 ${pageIndex + 1}:\n" +"媒体框 - 宽度: ${mediaBox.width}, 高度: ${mediaBox.height}\n" +"裁剪框 - 宽度: ${cropBox.width}, 高度: ${cropBox.height}\n" +"旋转角度: ${page.rotation}°\n" +"注释数量: ${page.annotations.size}"} catch (e: Exception) {"获取页面信息失败"}
}

6. 添加注释

添加文本注释
fun addTextAnnotation(document: PDDocument, pageIndex: Int, x: Float, y: Float, text: String) {try {val page = document.getPage(pageIndex)val annotation = PDAnnotationInk()annotation.subtype = "FreeText"// 设置注释位置和大小val rect = PDRectangle(x, y, x + 100, y + 50)annotation.rectangle = rect// 设置注释内容annotation.contents = text// 设置颜色annotation.color = AWTColor.YELLOW// 添加到页面page.annotations.add(annotation)} catch (e: Exception) {Log.e(TAG, "添加文本注释失败: ${e.message}")}
}
添加手绘注释
fun addInkAnnotation(document: PDDocument, pageIndex: Int, points: List<FloatArray>) {try {val page = document.getPage(pageIndex)// 创建手绘注释val inkAnnotation = PDAnnotationInk()inkAnnotation.subtype = "Ink"// 计算边界val bounds = calculateInkBounds(points, page.mediaBox)inkAnnotation.rectangle = bounds// 创建外观流val normalAppearance = PDAppearanceStream(document)normalAppearance.bBox = bounds// 绘制轨迹PDPageContentStream(document, normalAppearance).use { cs ->cs.setStrokingColor(AWTColor.RED)cs.setLineWidth(2f)for (path in points) {if (path.size >= 4) {cs.moveTo(path[0], path[1])for (index in 2 until path.size step 2) {cs.lineTo(path[index], path[index + 1])}cs.stroke()}}}// 设置外观val apDict = COSDictionary()apDict.setItem(COSName.N, normalAppearance)inkAnnotation.cosObject.setItem(COSName.AP, apDict)// 添加到页面page.annotations.add(inkAnnotation)} catch (e: Exception) {Log.e(TAG, "添加手绘注释失败: ${e.message}")}
}

7. 保存PDF文件

fun savePdf(document: PDDocument, outputPath: String): Boolean {return try {document.save(outputPath)true} catch (e: IOException) {false}
}

8. 关闭文档

fun closeDocument(document: PDDocument) {try {document.close()} catch (e: IOException) {Log.e(TAG, "关闭PDF文档失败: ${e.message}")}
}

使用示例

完整处理流程示例

fun processPdfExample(context: Context, fileName: String) {// 1. 加载PDFval document = loadPdfFromAssets(context, fileName)if (document == null) {Log.e(TAG, "无法加载PDF文件")return}try {// 2. 获取PDF信息val info = getPdfInfo(document)Log.i(TAG, "PDF信息:\n$info")// 3. 提取文本val text = extractText(document)Log.i(TAG, "PDF文本内容:\n$text")// 4. 获取第一页信息if (document.numberOfPages > 0) {val pageInfo = getPageInfo(document, 0)Log.i(TAG, "第一页信息:\n$pageInfo")// 5. 添加文本注释addTextAnnotation(document, 0, 100f, 100f, "这是一个测试注释")// 6. 添加手绘注释示例val samplePoints = listOf(floatArrayOf(50f, 50f, 100f, 100f, 150f, 50f),floatArrayOf(200f, 200f, 250f, 250f, 300f, 200f))addInkAnnotation(document, 0, samplePoints)}// 7. 保存修改后的PDFval outputPath = context.getExternalFilesDir(null)?.absolutePath + "/modified_$fileName"if (savePdf(document, outputPath)) {Log.i(TAG, "PDF处理完成,已保存到: $outputPath")}} finally {// 8. 关闭文档closeDocument(document)}
}

注意事项

  1. 内存管理: PDFBox需要大量内存,建议使用MemoryUsageSetting.setupMixed()来优化内存使用。

  2. 异常处理: 所有PDF操作都应该包含适当的异常处理。

  3. 资源释放: 使用完PDF文档后,务必调用close()方法释放资源。

  4. 线程安全: PDFBox操作应该在后台线程中执行,避免阻塞UI线程。

  5. 文件权限: 确保应用有适当的文件读写权限。

更多资源

  • PDFBox Android GitHub
  • PDFBox 官方文档
  • Android 开发文档
http://www.xdnf.cn/news/1251109.html

相关文章:

  • 【数据结构与算法】刷题篇——环形链表的约瑟夫问题
  • 8.6笔记
  • 93、【OS】【Nuttx】【构建】cmake menuconfig 目标
  • vxe-table表格编辑单元格,进行正则验证,不符合验证,清空单元格数据。
  • 【“连亏十年” 川机器人,启动科创板IPO辅导】
  • 短剧小程序系统开发:技术驱动下的内容创新之路
  • 后端服务oom
  • [linux] Linux系统中断机制详解及用户空间中断使用方法
  • Java技术栈/面试题合集(19)-架构设计篇
  • Android—服务+通知=>前台服务
  • 简单spring boot项目,之前练习的,现在好像没有达到效果
  • 攻防世界WEB(新手模式)20-unseping
  • Android14的QS面板的加载解析
  • Tesseract + Poppler 实现图片型 PDF 转文字
  • jmm 指令重排 缓存可见性 Volatile 内存屏障
  • Perforce P4 Plan - DevOps实时规划工具
  • Python day36
  • 基于单片机智能浇花/智能灌溉/智慧农业/智能大棚
  • 双馈和永磁风机构网型跟网型联合一次调频并入同步机电网,参与系统一次调频,虚拟惯量下垂,虚拟同步机VSG控制matlab/simulink
  • 【软考系统架构设计师备考笔记5】 - 专业英语
  • 【关于Java的泛型(基础)】
  • 《动手学深度学习》读书笔记—9.3深度循环神经网络
  • 阿里云 Flink
  • 第七章课后综合练习
  • SpringBoot 3.x整合Elasticsearch:从零搭建高性能搜索服务
  • 【网络基础】计算机网络发展背景及传输数据过程介绍
  • vue3 vite 使用vitest 单元测试 组件测试
  • Lesson 31 Success story
  • 【C++详解】STL-set和map的介绍和使用样例、pair类型介绍、序列式容器和关联式容器
  • 蓝桥杯----锁存器、LED、蜂鸣器、继电器、Motor