Android集成Smack混淆后运行时出现XmlPullParser异常求助
Android集成Smack混淆后初始化XMPP连接抛出ServiceConfigurationError的解决方案
问题描述
在Android中集成Smack库并配置混淆规则后,混淆代码运行时执行XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder();初始化XMPP连接,会抛出java.util.ServiceConfigurationError,根源是com.android.org.kxml2.io.KXmlParser.setFeature方法抛出org.xmlpull.v1.XmlPullParserException,提示不支持http://xmlpull.org/v1/doc/features.html#xml-roundtrip特性;未混淆代码时运行完全正常。
当前使用的混淆规则
-dontwarn org.xmlpull.v1.** -keep class org.jivesoftware.** { *; } -keep class org.xmlpull.** { *; } -keep class org.bouncycastle.jcajce.provider.** { *; } -keep class org.jivesoftware.smack.** { *; } -keep class org.jivesoftware.smackx.** { *; } -keepattributes Signature
报错日志
2023-01-12 12:28:56.673 32664-377/com.panasonic.promeet.debug E/AndroidRuntime: FATAL EXCEPTION: Thread-17 Process: com.panasonic.promeet.debug, PID: 32664 java.util.ServiceConfigurationError: z7.d: Provider a8.b could not be instantiated at java.util.ServiceLoader.fail(ServiceLoader.java:233) at java.util.ServiceLoader.-$$Nest$smfail(Unknown Source:0) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:392) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:416) at java.util.ServiceLoader$1.next(ServiceLoader.java:494) at z7.a.a(SmackXmlParser.java:44) at z7.a.b(SmackXmlParser.java:65) at v7.a0.h(PacketParserUtils.java:80) at n6.c0.d(SmackInitialization.java:159) at n6.c0.c(SmackInitialization.java:154) at n6.c0.<clinit>(SmackInitialization.java:103) at n6.x.b(Smack.java:38) at n6.x.a(Smack.java:64) at n6.p.<clinit>(ConnectionConfiguration.java:116) at t7.l.z(XMPPTCPConnectionConfiguration.java:64) at c4.e.n(XMPPConfigManager.java:189) at c4.e.q(XMPPConfigManager.java:292) at com.panasonic.promeet.utils.ProMeetApplication$d.run(ProMeetApplication.java:296) at java.lang.Thread.run(Thread.java:1012) Caused by: java.lang.ExceptionInInitializerError at java.lang.Class.newInstance(Native Method) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:388) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:416) at java.util.ServiceLoader$1.next(ServiceLoader.java:494) at z7.a.a(SmackXmlParser.java:44) at z7.a.b(SmackXmlParser.java:65) at v7.a0.h(PacketParserUtils.java:80) at n6.c0.d(SmackInitialization.java:159) at n6.c0.c(SmackInitialization.java:154) at n6.c0.<clinit>(SmackInitialization.java:103) at n6.x.b(Smack.java:38) at n6.x.a(Smack.java:64) at n6.p.<clinit>(ConnectionConfiguration.java:116) at t7.l.z(XMPPTCPConnectionConfiguration.java:64) at c4.e.n(XMPPConfigManager.java:189) at c4.e.q(XMPPConfigManager.java:292) at com.panasonic.promeet.utils.ProMeetApplication$d.run(ProMeetApplication.java:296) at java.lang.Thread.run(Thread.java:1012) Caused by: org.xmlpull.v1.XmlPullParserException: unsupported feature: http://xmlpull.org/v1/doc/features.html#xml-roundtrip (position:START_DOCUMENT null@1:1) at com.android.org.kxml2.io.KXmlParser.setFeature(KXmlParser.java:2102)
解决方案
修改混淆规则,补充以下内容,确保Smack依赖的SPI配置和XML解析类不被混淆:
# 保留ServiceLoader依赖的META-INF/services配置文件 -keepdir META-INF/services # 保留Smack XML解析相关的SPI接口和实现类名称 -keepnames class org.jivesoftware.smack.xml.XmlPullParserFactory -keepnames class org.jivesoftware.smack.xml.XmlPullParser -keepnames class org.jivesoftware.smack.xml.XmlSerializer # 保留所有实现Smack XML解析接口的类 -keep class * implements org.jivesoftware.smack.xml.XmlPullParserFactory { *; } -keep class * implements org.jivesoftware.smack.xml.XmlPullParser { *; } -keep class * implements org.jivesoftware.smack.xml.XmlSerializer { *; } # 确保Android系统的KXml解析器类不被混淆 -keep class com.android.org.kxml2.io.** { *; }
完整的混淆规则如下:
-dontwarn org.xmlpull.v1.** -keep class org.jivesoftware.** { *; } -keep class org.xmlpull.** { *; } -keep class org.bouncycastle.jcajce.provider.** { *; } -keep class org.jivesoftware.smack.** { *; } -keep class org.jivesoftware.smackx.** { *; } -keepattributes Signature # 新增的混淆规则 -keepdir META-INF/services -keepnames class org.jivesoftware.smack.xml.XmlPullParserFactory -keepnames class org.jivesoftware.smack.xml.XmlPullParser -keepnames class org.jivesoftware.smack.xml.XmlSerializer -keep class * implements org.jivesoftware.smack.xml.XmlPullParserFactory { *; } -keep class * implements org.jivesoftware.smack.xml.XmlPullParser { *; } -keep class * implements org.jivesoftware.smack.xml.XmlSerializer { *; } -keep class com.android.org.kxml2.io.** { *; }
原因分析
Smack通过**ServiceLoader(服务提供者接口)**动态加载XML解析器的实现类,这依赖两个关键要素:
META-INF/services目录下的配置文件,记录了接口对应的实现类全限定名;- 实现类的类名未被混淆,确保ServiceLoader能正确实例化类。
原混淆规则未保留META-INF/services目录,也未明确保护Smack XML解析相关的SPI类名,导致混淆后ServiceLoader无法找到正确的实现类,进而触发XML解析器特性设置异常。
内容的提问来源于stack exchange,提问作者Amrita Chaudhuri
相关产品推荐
相关产品推荐

