在Android中使用DigestUtils找不到的方法

Cau*_*ons 71 apache encryption android sha digest

我正在尝试使用JDK 1.6在Android 2.3.1中使用库DigestUtils,但是在执行应用程序时出现以下错误:

Could not find method org.apache.commons.codec.binary.Hex.encodeHexString, referenced from method org.apache.commons.codec.digest.DigestUtils.shaHex

在这里你有堆栈跟踪:

02-03 10:25:45.153: I/dalvikvm(1230): Could not find method org.apache.commons.codec.binary.Hex.encodeHexString, referenced from method org.apache.commons.codec.digest.DigestUtils.shaHex
02-03 10:25:45.153: W/dalvikvm(1230): VFY: unable to resolve static method 329: Lorg/apache/commons/codec/binary/Hex;.encodeHexString ([B)Ljava/lang/String;
02-03 10:25:45.153: D/dalvikvm(1230): VFY: replacing opcode 0x71 at 0x0004
02-03 10:25:45.153: D/dalvikvm(1230): VFY: dead code 0x0007-0008 in Lorg/apache/commons/codec/digest/DigestUtils;.shaHex ([B)Ljava/lang/String;
02-03 10:25:45.163: D/AndroidRuntime(1230): Shutting down VM
02-03 10:25:45.163: W/dalvikvm(1230): threadid=1: thread exiting with uncaught exception (group=0x40015560)
02-03 10:25:45.173: E/AndroidRuntime(1230): FATAL EXCEPTION: main
02-03 10:25:45.173: E/AndroidRuntime(1230): java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString
02-03 10:25:45.173: E/AndroidRuntime(1230):     at org.apache.commons.codec.digest.DigestUtils.md5Hex(DigestUtils.java:226)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at com.caumons.trainingdininghall.ConnectionProfileActivity.onCreate(ConnectionProfileActivity.java:20)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1586)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1638)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at android.app.ActivityThread.access$1500(ActivityThread.java:117)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:928)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at android.os.Looper.loop(Looper.java:123)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at android.app.ActivityThread.main(ActivityThread.java:3647)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at java.lang.reflect.Method.invokeNative(Native Method)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at java.lang.reflect.Method.invoke(Method.java:507)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
02-03 10:25:45.173: E/AndroidRuntime(1230):     at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)

导致异常的代码行是:

String hash = DigestUtils.shaHex("textToHash");

我在Android之外的Java类中执行了相同的代码,它的工作原理!所以,我不知道为什么在使用Android时它不起作用...我将libraty放在我的应用程序中的新libs /文件夹中并更新BuildPath以使用它.如果我尝试使用md5而不是sha1,我会得到相同的异常.任何帮助,将不胜感激!谢谢.

更新:

由于这是一个非常活跃的问题,我已经改变了接受的答案,转而支持@ DA25,因为他的解决方案很简单,大量的赞成证明它有效.

小智 138

我遇到了同样的问题,试图在我的Android应用中使用DigestUtils.这是我通过搜索找到的最佳答案,但我不愿意在更改名称空间的情况下重建.jar文件.在这个问题上花了一些时间之后,我找到了一种更简单的方法来解决我的问题.我的代码的问题陈述是

String s = DigestUtils.md5Hex(data);
Run Code Online (Sandbox Code Playgroud)

用以下内容替换此语句,它将起作用:

String s = new String(Hex.encodeHex(DigestUtils.md5(data)));
Run Code Online (Sandbox Code Playgroud)

同样,对于shaHex示例,您可以将其更改为

String hash = new String(Hex.encodeHex(DigestUtils.sha("textToHash")));
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为即使Android没有encodeHexString(),它也有encodeHex().希望这会帮助遇到同样问题的其他人.

  • 我不明白为什么只调用`Hex.encodeHex()`中的有问题的方法,并将结果设置为String构造函数适合你!你可以再详细一点吗?是DigestUtils库中的`encodeHex()`方法吗?你试过`new String(DigestUtils.md5(data));`直接? (7认同)
  • 出于某种原因,这实际上似乎工作:) (4认同)
  • 我知道这是一个老问题,但对于任何感兴趣的人:这是由Android捆绑自己版本的commons-codec 1.2引起的.任何比这更新的版本将无法在设备上使用. (3认同)

Ale*_*pov 34

由于对这个问题的根本原因没有明确的答案,我想澄清一下这里发生了什么.

为什么首先抛出NoSuchMethodError?

根据异常堆栈跟踪,导致错误的行在DigestUtils#md5hex方法中为226 .让我们看看我们在那里(我假设你已经使用了1.4版本,因为这是第Hex#encodeHexString226行中调用方法的唯一版本):

public static String md5Hex(String data) {
    return Hex.encodeHexString(md5(data));
}
Run Code Online (Sandbox Code Playgroud)

例外说java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString.让我们明白为什么.

首先,Android框架已经包含了Commons Codec库(除了DigestUtils类).是的,它不作为一部分曝光Android SDK,您不能直接使用它.但是你仍然想要使用它.那你干什么?您可以将Commons Codec库添加为应用程序的一部分.编译器没有抱怨 - 从他的观点来看一切都很好.

但是在运行时会发生什么?让我们按照您的异常堆栈跟踪:
首先,您DigestUtils#md5Hex从Activity的onCreate方法调用.正如我上面所写,框架不包含该类,因此DigestUtils(从Commons Codec版本1.4开始)从您的dex加载.
接下来,md5hex方法尝试调用Hex#encodeHexString方法.Hexclass是Commons Codec包含在框架中的库的一部分.问题是它的版本是1.3(从2004年7月开始发布).Hexclass存在于引导类路径中,这意味着运行时将始终支持它而不是Hex在dex中打包的类.启动应用程序时,您可以在应用程序日志中看到有关它的警告(使用Dalvik运行时):

D/dalvikvm? DexOpt: 'Lorg/apache/commons/codec/binary/Hex;' has an earlier definition; blocking out
I/dalvikvm? DexOpt: not resolving ambiguous class 'Lorg/apache/commons/codec/binary/Hex;'
D/dalvikvm? DexOpt: not verifying/optimizing 'Lorg/apache/commons/codec/binary/Hex;': multiple definitions
I/dalvikvm? Could not find method org.apache.commons.codec.binary.Hex.encodeHexString, referenced from method org.apache.commons.codec.digest.DigestUtils.md5Hex
Run Code Online (Sandbox Code Playgroud)

Hex #creditHexString方法是在1.4版本的Commons Codec库中引入的,因此在框架Hex类中不存在.运行时无法找到此方法,因此抛出NoSuchMethodError异常.

为什么接受答案的解决方案有效?

String s = new String(Hex.encodeHex(DigestUtils.md5(data)));
Run Code Online (Sandbox Code Playgroud)

首先,DigestUtils#md5调用方法.正如我已经说过的那样,DigestUtils将要使用的类是在你的dex中打包的类.此方法不使用任何其他Commons Codec类,因此没有问题.

接下来,Hex#encodeHex将被调用.Hex将使用的类是框架的类(版本1.3).该encodeHex方法(采用单个参数 - 字节数组)存在于Commons Codec库的1.3版本中,因此该代码可以正常工作.

我会建议什么?

我建议的解决方案是重命名classes namespace/package.通过这样做,我明确指定将执行哪些代码,并防止由于版本控制问题可能发生的奇怪行为.

你可以手动完成(正如Caumons在他的回答中所写),或者自动使用jarjar工具.

请参阅此问题摘要以及jarjar在我的博文中使用的提示.

  • 非常感谢你!我遇到了与Apache Commons Lang jar(3.2及以上版本)相同的问题 - 但仅限于供应商Xiomi的所有手机.显然,这些手机有旧版本的Apache Commons Lang作为系统运行时的一部分.所以我曾经得到如下例外:STACK_TRACE = java.lang.NoSuchMethodError:org.apache.commons.lang3.mutable.MutableBoolean.setTrue STACK_TRACE = java.lang.NoSuchMethodError:org.apache.commons.lang3.StringEscapeUtils.escapeXml10关注建议,我使用jarjar工具将包命名空间重命名为我的应用程序独有的东西. (3认同)
  • 谢谢,你激励我写了这个简单的展示项目 https://github.com/allpaykz/digest-utils (2认同)

Cau*_*ons 19

最后我得到答案,效果很好.正如在其他类型的加密(Base64)的Apache编解码器没有这样的方法错误中描述的那样,我试图重现相同的问题,我得到完全相同的错误.所以我是在附上问题的情况下.正如他们所说,它似乎是与包名称的内部名称冲突,org.apache.commons.codec正如@Don所说,我改变它com.apache.commons.codec并且工作正常!我是怎么做到的

我下载了源代码并将3个目录更改orgcom.我还将所有出现的软件包名称替换为它们出现的文件,并将文档中的引用更改为com/apache/commons/codec/.(不要试图手动重新制作它们,否则你将花费一天的时间).然后我编译了库并用Ant生成了jar,我打电话给他commons-codec-1.6-android.jar.我把jar放在libs/Android应用程序的文件夹中,并将其添加到buildpath中.另外,我将源附加为包含所有文件的文件夹.所以现在我已准备好与Android一起使用的库了!

希望它能帮助别人!

  • 这是正确的答案,但开发人员改变摘要来源似乎非常不可能.这应该报告给阿帕奇.在我的开发中,我选择了@ DA25给出的另一个选项 (2认同)