使用dom4j 2.1.3在andrioid手机上解析xml,并且开了混淆后,会报如下错误
at org.xml.sax.helpers.XMLReaderFactory.createXMLReader(XMLReaderFactory.java:159)
at org.dom4j.io.SAXHelper.createXMLReader(Unknown Source:7)
at org.dom4j.io.SAXReader.createXMLReader(Unknown Source:4)
at org.dom4j.io.SAXReader.getXMLReader(Unknown Source:4)
at org.dom4j.io.SAXReader.setFeature(Unknown Source:0)
at org.dom4j.io.SAXReader.createDefault(Unknown Source:8)
at uw.b(Unknown Source:0)
at uw.c(Unknown Source:9)
at uw.d(Unknown Source:28)
at sw.j(Unknown Source:12)
at bz$a.a(Unknown Source:18)
at bz$a.invoke(Unknown Source:2)
at com.huawei.hwncecommon.kt.KTHelperKt$doAsync$1.invoke(Unknown Source:4)
at com.huawei.hwncecommon.kt.KTHelperKt$doAsync$1.invoke(Unknown Source:0)
at com.huawei.hwncecommon.kt.KTHelperKt$sam$java_util_concurrent_Callable$0.call(Unknown Source:2)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
从log看像是 缺省了xml解析的驱动,但不开混淆的时候功能完全正常,这就可以肯定是混淆导致的。后面提交了一个issue给google的工程师,得到原因如下:
xmlpull与dom4j有冲突,内部都集成了pull-parse这个实现类,但R8在打包的时候,会把有冲突的貌似删除,dom4j 的xmlDriver在获取driver时是通过反射获取的。
dom4j解析xml源码如下:
public static XMLReader createXMLReader ()
throws SAXException
{
String className = null;
ClassLoader loader = NewInstance.getClassLoader ();
// 1. try the JVM-instance-wide system property
try { className = System.getProperty (property); }
catch (RuntimeException e) { /* normally fails for applets */ }
// 2. if that fails, try META-INF/services/
if (className == null) {
try {
String service = "META-INF/services/" + property;
InputStream in;
BufferedReader reader;
if (loader == null)
in = ClassLoader.getSystemResourceAsStream (service);
else
in = loader.getResourceAsStream (service);
if (in != null) {
try {
reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
className = reader.readLine();
} finally {
in.close(); // may throw IOException
}
}
} catch (Exception e) {
}
}
// 3. Distro-specific fallback
if (className == null) {
// BEGIN DISTRIBUTION-SPECIFIC
// EXAMPLE:
// className = "com.example.sax.XmlReader";
// or a $JAVA_HOME/jre/lib/*properties setting...
// END DISTRIBUTION-SPECIFIC }
// do we know the XMLReader implementation class yet?
if (className != null)
return loadClass (loader, className);
// 4. panic -- adapt any SAX1 parser
try {
return new ParserAdapter (ParserFactory.makeParser ());
} catch (Exception e) {
throw new SAXException ("Can't create default XMLReader; "
+ "is system property org.xml.sax.driver set?");
}
}
这是googlel回复的原话
Thank you for the report. The reason for the warning is that the class
org.xmlpull.v1.XmlPullParser
is part of the Android runtime (https://developer.android.com/reference/org/xmlpull/v1/XmlPullParser) and also pulled in throughdom4j
or a dependency hereof. When compiling with R8 the classes in the program takes precedence, but at runtime the it it the runtime which will be loaded. To get rid of the warning I suggest that you sanitizedom4j
and dependencies to remove the classes which are already in the Android library, and continue from there.However, whether the warning is the reason for the runtime error I cannot say for sure. If the definitions of the duplicate interfaces/classes are the same then the code should work.
Alternatively you can take a look at Parse XML data, which gives some recommendations on how to handle XML data on Android.
解决方案如下:在gradle中排除冲突的模块
implementation('org.dom4j:dom4j:2.1.3') {
exclude group: 'pull-parser', module: 'pull-parser'
}