Android10上”org.apache.commons.codec.binary.Hex ClassNotFoundException“解决及原因探究

在一次版本迭代后,突然在部分机型上爆出了一些崩溃,查看崩溃原因,原因内容是java.lang.NoClassDefFoundError:Failed resolution of: Lcom/apache/commons/desc/binary/Hex,具体如下图:

比较蛋疼的是在这次版本迭代后才出现这个问题,而且是高版本手机有问题,10.0的测试机有问题,6.0的测试却没问题。

问题定位及解决

基于上述不同机型的表现,用代码验证下,org.apache.commons.codec.binary.Hex这个类的加载情况,验证代码如下:

try {
    Class.forName("org.apache.commons.codec.binary.Hex");
    Log.e("HexTest","success");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
    Log.e("HexTest","failed");
}

经过验证,在10.0的手机上输出的是falied,6.0的手机上输出的是success

org.apache.commons.codec.binary.Hex这个类到底是干嘛的?是哪个包下的呢?
全局搜索项目代码,没发现org.apache.commons.codec.binary.Hex,这就表示这个类不是我们项目自己添加的依赖。

为了先解决问题,我就找到了相应的jar包,具体位于Apache Commons Codec,通过下面的方式给项目添加了依赖:

    compile group: 'commons-codec', name: 'commons-codec', version: '1.14'

问题暂时解决了。

问题原因分析

接下来我们来分析下出现这个问题的原因,问题的核心在于6.0的手机上是可以加载到这个类的,10.0的手机加载不到,初步猜测是手机系统内置了这个类,高版本的手机默认把这个类给hide了。

后来经过详细的排查本次迭代的代码,发现了一处可能的原因,就是编译版本compileSdkVersion27升级到了28,然后把compileSdkVersion回退到27,这个问题果然没了。

api 28对应的是Android 9,具体对应关系请看Android version history

emmmmmm,现在的问题是compileSdkVersion从27到28,跟这个apache的包hide起来有什么关系?

突然想起来Android6.0(也就是api 23)中移除了对Apache HTTP客户端的支持,这个也是apache包,他们之间是不是有什么关系呢?我们看下官网,它的解释是这样的:

Apache HTTP 客户端弃用
在 Android 6.0 中,我们移除了对 Apache HTTP 客户端的支持。从 Android 9 开始,该内容库已从 bootclasspath 中移除,且默认情况下应用无法使用它。

我们找一个org.apache.http.legacy的jar包分析一下,具体如下:

org.apache.http.legacy包下有我们想要的org.apache.commons.codec.binary.Hex类,那么我们可以参照官网提供的在高版本使用org.apache.http.legacy建议即可,具体参考Apache HTTP 客户端弃用

我们只需要在AndroidManifest.xml中添加以下内容即可:

<uses-library
    android:name="org.apache.http.legacy"
    android:required="false" />

当然了,我们还可以用另一种方式,在模块的build.gradle中添加如下代码即可:

android { 
    useLibrary ‘org.apache.http.legacy'
}

需要说明的是,我们每个版本的Android sdk中其实都是有org.apache.http.legacy的jar包的,具体位于sdk/platforms/android-xx/options/路径下,如下图:

至此,出现问题的原因搞明白了,我们平时能引用到org.apache.commons.codec.binary.Hex类或者org.apache.commons.codec.binary.Base64这些类,是因为Android自带的org.apache.http.legacyjar包中包含了它们。如果你项目的compileSdkVersionapi 28及以上,那你就需要注意下这个问题了。

参考

Apache HTTP 客户端弃用

### 回答1: org.apache.commons.codec.binary.hex是一个Java编程语言中的类库,用于将二进制数据转换为十六进制字符串,或将十六进制字符串转换为二进制数据。它是Apache Commons Codec项目的一部分,提供了一些常见的编码和解码功能。 ### 回答2: org.apache.commons.codec.binary.hexApache Commons Codec库中提供的一个Java类,用于在字节数组和十六进制字符串之间进行转换。 在计算机网络传输中,往往需要将二进制数据转换为文本格式传输,例如在HTTP协议的请求体中,可能需要传输图片或者文件等二进制数据。而在文本与二进制之间的转换过程中,十六进制字符串是一种常见的格式,因为十六进制字符串由16个字符构成,每个字符表示4位二进制数,便于传输和处理。 org.apache.commons.codec.binary.hex内部实现了将字节数组转换为十六进制字符串的方法,以及将十六进制字符串转换为字节数组的方法。在使用该类时,我们可以通过编写代码调用这些方法来实现需要的转换。例如,如果我们有一个字节数组byte[],想要将其转换为十六进制字符串,可以按照以下代码进行操作: String hexString = Hex.encodeHexString(byte[] data); 其中,Hex.encodeHexString是org.apache.commons.codec.binary.hex中的一个静态方法,用于将字节数组转换为十六进制字符串。同样的,如果需要将一个十六进制字符串还原为字节数组,可以按照以下代码进行操作: byte[] data = Hex.decodeHex(String hexString.toCharArray()); 在以上代码中,Hex.decodeHexorg.apache.commons.codec.binary.hex中的一个静态方法,用于将十六进制字符串转换为字节数组。需要注意的是,由于十六进制字符串中的每个字符表示4位二进制数,因此在还原时需要先将字符串转换为字符数组,然后才能进行还原。 总之,org.apache.commons.codec.binary.hex是一个非常有用的Java类,可以帮助我们在字节数组和十六进制字符串之间进行转换,并且其内部实现十分高效。在进行二进制数据的文本化传输时,我们可以利用该类来实现需要的处理。 ### 回答3: org.apache.commons.codec.binary.hex是一个Apache Commons Codec库的Java类,提供了十六进制编码和解码的实现。十六进制编码是将二进制数据转换为易于传输和使用的文本格式的过程,可以用于加密、数据传输等领域。 在Java中,可以使用该库对二进制数据进行编码和解码操作。具体来说,org.apache.commons.codec.binary.hex中提供以下方法: 1. encodeHex:实现对二进制数据的十六进制编码,返回一个字符数组。 2. decodeHex:实现对十六进制编码的解码,返回一个字节数组。 3. encodeHexString:实现对二进制数据的十六进制编码,返回一个字符串。 4. decodeHexString:实现对十六进制编码的解码,返回一个字节数组。 在实际应用中,org.apache.commons.codec.binary.hex经常被用于网络通信、文件传输、加密解密以及各种数据格式的转换等场景。例如,可以使用该库将图片文件转换为十六进制编码后进行网络传输,也可以使用该库对加密后的数据进行解码。 总之,org.apache.commons.codec.binary.hex提供了易于使用的十六进制编码和解码工具,方便了开发人员进行数据操作和数据传输工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tinyvampirepudge

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值