R8: Library class android.content.res.XmlResourceParser implements program class org.xmlpull.v1.XmlP

 使用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 through dom4j 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 sanitize dom4j 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'
    }

google issue链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,这个问题可能是由以下两个原因之一引起的: 1. 缺少字体文件 2. build-tools版本与项目的版本不一致 以下是解决这两个问题的方法: 1. 如果缺少字体文件,请按照以下步骤将字体文件添加到您的项目中: - 将字体文件复制到您的项目的android/app/src/main/assets/fonts/目录下。 - 在您的项目的android/app/build.gradle文件中添加以下代码: ```gradle project.ext.react = [ ... extraPackagerArgs: ["--assetExts", "ttf"] ] ``` - 在您的项目的android/app/src/main/java/com/yourproject/MainApplication.java文件中添加以下代码: ```java package com.yourproject; import android.graphics.Typeface; import com.facebook.react.ReactApplication; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; import java.util.Arrays; import java.util.List; public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage() ); } @Override protected String getJSMainModuleName() { return "index"; } @Override protected String getJSBundleFile() { return "assets://index.android.bundle"; } @Override protected String getBundleAssetName() { return "index.android.bundle"; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/YourFont.ttf"); } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); } } ``` 2. 如果build-tools版本与项目的版本不一致,请按照以下步骤解决: - 运行flutter doctor -v命令,查看您的Flutter环境是否正常。 - 确保您的项目的build.gradle文件中的buildToolsVersion与您的Android SDK中安装的build-tools版本相同。 - 如果您的Android SDK中没有安装所需的build-tools版本,请打开Android Studio并安装它们。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值