You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android发布版ProGuard适配POI Excel库崩溃问题排查

Android Release构建中POI Excel处理崩溃的ProGuard规则问题

Android项目集成了POI等Excel处理依赖,Debug构建正常,但Release构建调用Excel相关方法时崩溃。现有ProGuard规则已保留多个相关包,附上依赖配置、报错栈及出错函数,请问我的ProGuard规则是否遗漏内容?

编辑:已更新依赖信息
编辑2:已更新报错相关函数

依赖配置

implementation group: 'org.apache.poi', name: 'poi-ooxml', version: '3.17'
implementation group: 'org.apache.xmlbeans', name: 'xmlbeans', version: '3.1.0'
implementation 'com.fasterxml:aalto-xml:1.2.2'
implementation("it.skrape:skrapeit:1.2.2")

现有ProGuard配置

-keep class org.apache.poi.** {*;}
-keep class org.apache.xmlbeans.** {*;}
-keep class com.fasterxml.** {*;}
-keep class com.microsoft.schemas.** {*;}
-keep class org.openxmlformats.** {*;}
-keep class org.openxmlformats.schemas.** {*;}
-keep class schemaorg_apache_xmlbeans.** {*;}

完整报错栈

java.lang.ExceptionInInitializerError
    at org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader(Unknown Source:0)
    at j7.a.a(SourceFile:2)
    at org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook.<clinit>(SourceFile:1)
    at org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook$Factory.newInstance(Unknown Source:0)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.onWorkbookCreate(SourceFile:1)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(SourceFile:5)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(SourceFile:1)
    at com.shervinkoushan.anyTracker.shared.utils.FileUtils.pointsToWorkBook(SourceFile:2)
    at com.shervinkoushan.anyTracker.shared.utils.FileUtils.dataPointsToExcelFile(SourceFile:1)
    at f9.k.invokeSuspend(SourceFile:17)
    at sa.a.resumeWith(SourceFile:3)
    at qd.o0.run(SourceFile:18)
    at xd.a$a.run(SourceFile:14)
Caused by: java.lang.IllegalStateException: Cannot load nodeToCursor: verify that xbean.jar is on the classpath
    at org.apache.xmlbeans.XmlBeans.buildMethod(SourceFile:4)
    at org.apache.xmlbeans.XmlBeans.buildNodeMethod(Unknown Source:18)
    at org.apache.xmlbeans.XmlBeans.buildNodeToCursorMethod(Unknown Source:4)
    at org.apache.xmlbeans.XmlBeans.<clinit>(SourceFile:11)
    ... 13 more
Caused by: java.lang.NoSuchMethodException: org.apache.xmlbeans.impl.store.Locale.nodeToCursor [interface org.w3c.dom.Node]
    at java.lang.Class.getMethod(Class.java:2103)
    at java.lang.Class.getMethod(Class.java:1724)
    at org.apache.xmlbeans.XmlBeans.buildMethod(SourceFile:1)
    ... 16 more

报错相关函数

fun pointsToWorkBook(
    dataPoints: List<DataPoint>, textPoints: List<TextPoint>, trackedElement: TrackedElement,
    isText: Boolean, context: Context
): Workbook {
    initPoi()
    val workbook = XSSFWorkbook()
    val sheet = workbook.createSheet(stringToValidFileName(trackedElement.title))

    val titleCell = sheet.createRow(0).createCell(0)
    titleCell.setCellValue(trackedElement.title)
    val font = workbook.createFont()
    font.bold = true
    val titleStyle = workbook.createCellStyle()
    titleStyle.setFont(font)
    titleCell.cellStyle = titleStyle

    val linkFont = workbook.createFont()
    linkFont.underline = Font.U_SINGLE
    linkFont.color = IndexedColors.BLUE.getIndex()
    val anyTrackerCell = sheet.createRow(2).createCell(0)
    val anyTrackerString = XSSFRichTextString("Tracking with AnyTracker")
    anyTrackerString.applyFont(14, 24, linkFont)
    anyTrackerCell.setCellValue(anyTrackerString)
    val link = workbook.creationHelper.createHyperlink(HyperlinkType.URL)
    link.address = "https://play.google.com/store/apps/details?id=com.shervinkoushan.anyTracker"
    anyTrackerCell.hyperlink = link

    val infoCell = sheet.createRow(3).createCell(0)
    val trackedInfo = StringUtils.getTrackedInfo(trackedElement, context)
    infoCell.setCellValue(trackedInfo)
    trackedElement.websiteBundle?.websiteUrl?.let { url ->
        val websiteLink = workbook.creationHelper.createHyperlink(HyperlinkType.URL)
        websiteLink.address = url
        infoCell.hyperlink = websiteLink
        val richString = XSSFRichTextString(StringUtils.getTrackedInfo(trackedElement, context))
        val startIndex = trackedInfo.indexOf(url)
        richString.applyFont(startIndex, startIndex + url.length, linkFont)
        infoCell.setCellValue(richString)
    }
    val header = sheet.createRow(5)
    header.createCell(1).setCellValue("Date")
    sheet.setColumnWidth(0, 23 * 260)
    sheet.setColumnWidth(1, 16 * 260)

    val dateFormat = workbook.creationHelper.createDataFormat().getFormat("dd.mm.yyyy hh:mm")
    val dateStyle = workbook.createCellStyle()
    dateStyle.setBorderLeft(BorderStyle.THIN)
    dateStyle.setBorderRight(BorderStyle.THIN)
    dateStyle.dataFormat = dateFormat
    dateStyle.setAlignment(HorizontalAlignment.LEFT)
    val bottomDateStyle = workbook.createCellStyle()
    bottomDateStyle.setBorderLeft(BorderStyle.THIN)
    bottomDateStyle.setBorderBottom(BorderStyle.THIN)
    bottomDateStyle.setBorderRight(BorderStyle.THIN)
    bottomDateStyle.dataFormat = dateFormat
    bottomDateStyle.setAlignment(HorizontalAlignment.LEFT)
    val valueStyle = workbook.createCellStyle()
    valueStyle.setBorderRight(BorderStyle.THIN)
    val bottomValueStyle = workbook.createCellStyle()
    bottomValueStyle.setBorderRight(BorderStyle.THIN)
    bottomValueStyle.setBorderBottom(BorderStyle.THIN)

    if (isText) {
        sheet.setColumnWidth(
            2, max("Value".length, textPoints.maxOfOrNull { it.text.length } ?: 0
            ) * 250
        )
        header.createCell(2).setCellValue("New text")
        textPoints.forEachIndexed { index, textPoint ->
            val row = sheet.createRow(index + 6)
            val dateCell = row.createCell(1)
            dateCell.setCellValue(Date.from(textPoint.date))
            val valueCell = row.createCell(2)
            valueCell.setCellValue(textPoint.text)
            if (index == textPoints.size - 1) {
                dateCell.cellStyle = bottomDateStyle
                valueCell.cellStyle = bottomValueStyle
            } else {
                dateCell.cellStyle = dateStyle
                valueCell.cellStyle = valueStyle
            }
        }
    } else {
        sheet.setColumnWidth(
            2, max("Value".length, dataPoints.maxOfOrNull { it.value.toString().length } ?: 0
            ) * 320
        )
        header.createCell(2).setCellValue("Value")
        dataPoints.forEachIndexed { index, dataPoint ->
            val row = sheet.createRow(index + 6)
            val dateCell = row.createCell(1)
            dateCell.setCellValue(Date.from(dataPoint.date))
            val valueCell = row.createCell(2)
            valueCell.setCellValue(dataPoint.value.toString())
            if (index == dataPoints.size - 1) {
                dateCell.cellStyle = bottomDateStyle
                valueCell.cellStyle = bottomValueStyle
            } else {
                dateCell.cellStyle = dateStyle
                valueCell.cellStyle = valueStyle
            }
        }
    }

    val headerStyle = workbook.createCellStyle()
    headerStyle.setBorderTop(BorderStyle.THIN)
    headerStyle.setBorderBottom(BorderStyle.THIN)
    headerStyle.setBorderLeft(BorderStyle.THIN)
    headerStyle.setBorderRight(BorderStyle.THIN)
    header.getCell(1).cellStyle = headerStyle
    header.getCell(2).cellStyle = headerStyle

    return workbook
}

我尝试过Stack Overflow上的多种配置但无效,请问我的ProGuard规则是否存在遗漏?


内容的提问来源于stack exchange,提问作者shko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:45:47