在Android中未find使用DigestUtils的方法

我试图在Android 2.3.1中使用库DigestUtils使用JDK 1.6,但是当执行应用程序时,我得到以下错误:

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) 

导致exception的代码行是:

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

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

更新:

由于这是一个非常活跃的问题,我已经改变了接受@ DA25的答案,因为他的解决scheme很简单,大量的upvotescertificate了它的工作原理。

我遇到了同样的问题,试图在我的Android应用程序中使用DigestUtils。 这是我可以通过searchfind的最好的答案,但我不愿意重build名称空间更改的.jar文件。 花了一些时间在这个问题上,我发现一个更简单的方法来解决我的情况下的问题。 我的代码的问题声明是

 String s = DigestUtils.md5Hex(data); 

用下面的语句replace这个语句,它将起作用:

 String s = new String(Hex.encodeHex(DigestUtils.md5(data))); 

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

 String hash = new String(Hex.encodeHex(DigestUtils.sha("textToHash"))); 

这是有效的,因为即使Android没有encodeHexString(),它也有encodeHex()。 希望这能帮助那些遇到同样问题的人。

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

为什么NoSuchMethodError首先被抛出?

根据exception堆栈跟踪,导致故障的线路在DigestUtils#md5hex方法中为226。 让我们看看我们在那里 (我假设你已经使用了1.4版本,因为这是唯一的版本,在第226行调用Hex#encodeHexString方法):

 public static String md5Hex(String data) { return Hex.encodeHexString(md5(data)); } 

java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexStringexception说明java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString 。 让我们来了解为什么。

首先,Android框架已经包含了Commons Codec库(除了DigestUtils类)。 是的,它不是作为Android SDK一部分公开的,你不能直接使用它。 但是你仍然想要使用它。 那你干什么? 您添加Commons Codec库作为您的应用程序的一部分。 编译器不抱怨 – 从他的angular度来看,一切都很好。

但是在运行时会发生什么? 让我们按照你的exception堆栈跟踪:
首先,从Activity的onCreate方法调用DigestUtils#md5Hex 。 正如我上面写的,框架不包括那个类,所以DigestUtils (来自Commons Codec版本1.4)从你的dex被加载。
接下来, md5hex方法尝试调用Hex#encodeHexString方法。 Hex类是包含在框架中的Commons Codec库的一部分。 事情是,它的版本是1.3 (古代从2004年7月发布)。 启动类path中存在Hex类,这意味着运行时将永远支持它,而不是包装在您的dex中的Hex类。 在启动应用程序(使用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 

Hex#encodeHexString方法在Commons Codec库的1.4版本中引入,因此在框架的Hex类中不存在。 运行时无法find此方法,从而引发NoSuchMethodErrorexception。

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

 String s = new String(Hex.encodeHex(DigestUtils.md5(data))); 

首先, DigestUtils#md5方法。 正如我已经说过的,将使用的DigestUtils类是包装在你的dex中的类。 这种方法不使用任何其他的Commons Codec类,所以没有问题。

接下来, Hex#encodeHex将被调用。 将被使用的Hex类是框架的一个(版本1.3)。 Commons Codec库1.3版本中存在encodeHex方法(只有一个参数 – 字节数组),因此这段代码可以正常工作。

我会build议什么?

我build议的解决scheme是重命名类命名空间/包。 通过这样做,我明确指定要执行的代码,并防止由于版本问题而可能发生的奇怪行为。

你可以手动做(如Caumons在他的答案中写的),或自动与jarjar工具。

看到这个问题总结和在我的jarjar中使用jarjar提示。

最后我得到答案,它运作良好。 正如Apache编解码器中另一种types的encryption(Base64)中没有这样的方法错误,我试图重现相同的问题,我得到完全相同的错误。 所以我是在附加问题的情况下。 正如他们所说,它似乎是一个内部名称与包名称org.apache.commons.codec相撞,正如@Don所述,我将其更改为com.apache.commons.codec ,工作正常! 我是怎么做到的?

我下载了源代码,并将3个目录org更改为com 。 我也replace了出现在文件中的所有包名,并将文档中的引用改为com/apache/commons/codec/ 。 (不要试图手动留下他们,否则你会花这个洞)。 然后,我编译了库,并用Ant生成了jar,我把它叫做commons-codec-1.6-android.jar 。 我把jar放在我的Android应用程序的libs/文件夹中,并将其添加到构buildpath中。 另外,我将源文件作为包含所有文件的文件夹。 所以现在我已经可以使用Android库了!

希望它能帮助别人!

谢谢@ DA25

这对我来说工作得很好

我有添加依赖项

 compile 'commons-codec:commons-codec:1.9' 

ref: http : //mvnrepository.com/artifact/commons-codec/commons-codec/1.9

我的function

 public String encode(String key, String data) { try { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); sha256_HMAC.init(secret_key); return new String(Hex.encodeHex(sha256_HMAC.doFinal(data.getBytes("UTF-8")))); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } 

对于我来说,proguard在混淆的时候删除了这个类。将它添加到你的Proguard规则中。

 -keep class org.apache.commons.** { *; } 

这里是我使用的Apache包的方法。

 Hex.encodeHex(digest)