Excel 的 Proguard 规则在发布版本上失败 - Android

问题描述 投票:0回答:2

编辑:使用依赖项更新

编辑 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)
    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.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)
    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) 
    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) 

导致错误的函数:

    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
    }

我的 proguard 文件中是否缺少任何内容?我尝试了 Stack Overflow 上的各种代码片段,但没有成功。

android apache-poi proguard
2个回答
1
投票

您可以使用

-keep class !com.your.package.** { *; }
将所有内容保留在您自己的包的文件之外。


0
投票

这些 ProGuard 规则对我有用:

# Apache POI
-dontwarn com.github.luben.**
-dontwarn com.microsoft.**
-dontwarn com.sun.**
-dontwarn java.awt.**
-dontwarn javax.**
-dontwarn org.apache.**
-dontwarn org.bouncycastle.**
-dontwarn org.brotli.**
-dontwarn org.etsi.**
-dontwarn org.ietf.**
-dontwarn org.openxmlformats.**
-dontwarn org.tukaani.**
-dontwarn org.w3.**
-keep class com.microsoft.** { *; }
-keep class javax.** { *; }
-keep class org.apache.** { *; }
-keep class org.etsi.** { *; }
-keep class org.openxmlformats.** { *; }
-keep class org.w3.** { *; }
-keep class org.w3c.** { *; }
-keep class org.xml.sax.** { *; }
-keep class schemaorg_apache_xmlbeans.** { *; }

我的依赖项

build.gradle.kts

// Spreadsheets
// Don't update unless necessary. These library versions are compatible with Android 5.1 (API 22) and above
implementation("org.apache.poi:poi:4.0.1")
implementation("org.apache.poi:poi-ooxml:4.0.1")
implementation("org.apache.poi:poi-ooxml-schemas:4.0.1") {
    exclude("org.apache.xmlbeans")
}
implementation("xerces:xercesImpl:2.12.0")

我正在使用 Apache POI 创建带有图像的

XLSX
电子表格文件。

如果你只想排除那些真正需要保留的类,在发布版本之后,你可以在文件中查看ProGuard检测到的所有入口点

build\outputs\mapping\release\seeds.txt
,以及
build\outputs\mapping\release\usage.txt
中删除的代码。

© www.soinside.com 2019 - 2024. All rights reserved.