在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.encodeHexString
exception说明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此方法,从而引发NoSuchMethodError
exception。
为什么接受答案的解决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)