Способ не найден с помощью DigestUtils в Android
Я пытаюсь использовать библиотеку DigestUtils в Android 2.3.1 с помощью JDK 1.6, однако я получаю следующую ошибку при выполнении приложения:
Could not find method org.apache.commons.codec.binary.Hex.encodeHexString, referenced from method org.apache.commons.codec.digest.DigestUtils.shaHex
здесь у вас есть stacktrace:
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.access00(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)
строка кода, которая вызывает исключение:
String hash = DigestUtils.shaHex("textToHash");
Я выполнил тот же код в классе Java за пределами Android, и он работает! Так, я не знаю, почему при работе с Android это не работает... Я поместите libraty в новую папку libs / в моем приложении и обновите путь сборки, чтобы использовать его. Если я пытаюсь использовать md5 вместо sha1, я получаю то же исключение. Любая помощь будет оценена! Спасибо.
обновление:
поскольку это очень активный вопрос, я изменил принятый ответ в пользу @DA25, поскольку его решение является простым, и большое количество upvotes доказывает, что оно работает.
6 ответов:
я столкнулся с той же проблемой, пытаясь использовать DigestUtils в моем приложении для Android. Это был лучший ответ, который я мог найти, ища, но я не хотел перестраивать .файл jar с измененным пространством имен. Потратив некоторое время на эту проблему, я нашел более простой способ решить проблему для моего случая. Постановка задачи для моего кода была
String s = DigestUtils.md5Hex(data);замените это утверждение следующим, и оно будет работать:
String s = new String(Hex.encodeHex(DigestUtils.md5(data)));аналогично, для примера shaHex, вы можете измените его на
String hash = new String(Hex.encodeHex(DigestUtils.sha("textToHash")));это работает, потому что, хотя Android не имеет encodeHexString (), у него есть encodeHex(). Надеюсь, это поможет другим, кто сталкивается с той же проблемой.
поскольку нет четкого ответа на основную причину этой проблемы, я хотел бы уточнить, что здесь происходит.
почему NoSuchMethodError бросается в первую очередь?
согласно трассировке стека исключений, линия, которая вызывает ошибку, составляет 226 в
DigestUtils#md5hexметод. Давайте посмотрим, что у нас есть здесь (я предполагаю, что вы использовали версию 1.4, так как это единственный релиз, гдеHex#encodeHexStringметод вызывается в соответствии 226):public static String md5Hex(String data) { return Hex.encodeHexString(md5(data)); }исключение говорит
java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString. Давайте разберемся, почему.прежде всего, Android framework уже включает в себя
Commons Codecбиблиотека (кромеDigestUtilsкласс). Да, он не выставляется как частьAndroid SDKи вы не можете использовать его напрямую. Но вы все равно хотите его использовать. Так что же ты делаешь? Вы добавляетеCommons Codecбиблиотека как часть вашего приложения. Компилятор не жалуется - с его точки зрения все было хорошо.но что произойдет во время выполнения? Давайте следовать вашей трассировке стека исключений:
Во-первых, вы звонитеDigestUtils#md5Hexот вашей деятельностиonCreateметод. Как я уже писал выше, фреймворк не включает этот класс, поэтомуDigestUtils(отCommons Codecверсия 1.4) загружается с вашего dex.
Далее,md5hexметод пытается вызватьHex#encodeHexStringметод.Hexкласс является частьюCommons Codecбиблиотека, включенная в фреймворк. Дело в том, что его версия 1.3 (древний релиз от июля 2004).Hexкласс существует в boot classpath, что означает, что среда выполнения всегда будет поддерживать его вместоHexкласс, который упакован внутри вашего dex. Вы можете увидеть предупреждения об этом в журналах приложений при запуске приложения (с Dalvik runtime):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.md5HexHex#encodeHexString метод был введен в версии 1.4
Commons Codecбиблиотека и поэтому она не существует в рамкахHexкласса. Среда выполнения не может найти этот метод и таким образом бросаетNoSuchMethodErrorисключения.почему решение принятого ответа работает?
String s = new String(Hex.encodeHex(DigestUtils.md5(data)));первый,
DigestUtils#md5метод называется. Как я уже говорил,DigestUtilsкласс, который будет использоваться, - это тот, который упакован в ваш dex. Этот метод не использует никаких другихCommons Codecклассы, так что никаких проблем с этим.далее
Hex#encodeHexбудет называться. ЭлементHexкласс, который будет использоваться, является одним из фреймворков (версия 1.3). ЭлементencodeHexспособ (что принимает один параметр-байтовый массив) существует в версии 1.3Commons Codecбиблиотека, и поэтому этот код будет работать нормально.что бы я предложил?
мое предлагаемое решение-переименовать пространство имен классов / пакет. Таким образом, я явно указываю, какой код будет выполняться, и предотвращаю странное поведение, которое может возникнуть из-за проблем с версиями.
вы можете сделать это вручную (как написал Комонс в своем ответе), или автоматически с Джаджа.
см. эту проблему резюме и советы по использованию
jarjarв своем blogpost.
наконец, я получаю ответ, и он работает хорошо. Как описано в нет такой ошибки метода в кодеке Apache для другого типа шифрования (Base64) я попытался воспроизвести ту же проблему, и я получаю точно такую же ошибку. Так что я был в случае вопроса прилагается. Как говорится, это похоже на внутреннее столкновение имени с именем пакета
org.apache.commons.codecи как указано @Don я изменил его наcom.apache.commons.codecи работал нормально! Как я это сделал?Я скачал исходный код и поменял 3 директории
orgдоcom. Я также заменил все вхождения имени пакета в файлах, где они появляются, а также изменил ссылки на документыcom/apache/commons/codec/. (Не пытайтесь переделать их вручную, или вы проведете день отверстия). Затем я скомпилировал библиотеку и сгенерировал банку с Ant, которую я назвалcommons-codec-1.6-android.jar. Я поставил банку вlibs/папка моего приложения для Android и добавил его в путь к зданию. Кроме того, я прикрепил источники в качестве папки, которая содержит все файлы. Так что теперь у меня есть библиотека готова к использованию с Android!надеюсь, что это поможет кому-то еще!
спасибо @DA25
это работает нормально для меня
у меня есть добавить зависимость
compile 'commons-codec:commons-codec:1.9'ref:http://mvnrepository.com/artifact/commons-codec/commons-codec/1.9
моя функция
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 удалил класс во время обфускации .Добавить в ваши правила должны быть.
-keep class org.apache.commons.** { *; }вот метод, который я использовал из пакета apache.
Hex.encodeHex(digest)
добавить способ
public static String byteArrayToHexString(byte[] bytes) { final char[] toDigits = "0123456789abcdef".toCharArray(); int l = bytes.length; char[] out = new char[l << 1]; int i = 0; for (int j = 0; i < l; ++i) { out[(j++)] = toDigits[((0xF0 & bytes[i]) >>> 4)]; out[(j++)] = toDigits[(0xF & bytes[i])]; } return new String(out); }
Comments