编辑:使用依赖项更新
编辑 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 上的各种代码片段,但没有成功。
您可以使用
-keep class !com.your.package.** { *; }
将所有内容保留在您自己的包的文件之外。
这些 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
中删除的代码。