Что такое "android.security.MessageDigest"?
Одна из нескольких тысяч клиентов сообщила об ошибке в одном из моих приложений. Ошибка:
java.lang.NoClassDefFoundError - android.security.MessageDigest
Я не использую этот класс/метод в своих приложениях. Google Mapkey должен быть в порядке, потому что тысячи поддерживают одно и то же приложение с одной и той же версией. Здесь stacktrace:
java.lang.NoClassDefFoundError: android.security.MessageDigest
at com.google.android.maps.KeyHelper.getSignatureFingerprint(KeyHelper.java:60)
at com.google.android.maps.MapActivity.createMap(MapActivity.java:552)
at com.google.android.maps.MapActivity.onCreate(MapActivity.java:422)
at xx.yyy.zzzz.MyMapActivity.onCreate(MyMapActivity.java:41)
at xx.yyy.zzzz.TheMap.onCreate(TheMap.java:89)
at android.app.Activity.performCreate(Activity.java:4465)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Что это?
Спасибо заранее.
Ответы
Ответ 1
Класс MessageDigest - это вспомогательный класс, используемый для кодирования/декодирования ключей с использованием общих методов, таких как MD5 или SHA-1.
Кажется, что класс android.security.MessageDigest был удален из Honeycomb и более поздних выпусков Android и должен быть заменен на java.security.MessageDigest(посмотреть на этой странице)
Попробуйте загрузить последнюю версию API Карт Google и перестроить свое приложение с установленным максимальным значением targetSDK (на сегодняшний день это должно быть 16/желе Bean).
Ответ 2
Я потратил некоторое время на изучение этой проблемы, и я документирую то, что нашел здесь, в надежде, что это избавит других людей от неприятностей.
Ошибка - это результат изготовления устройства или создателя ПЗУ с использованием старой библиотеки изображений с новой версией Android. Как правило, это изолировано от скрытых таблеток, но теоретически может появляться в других ситуациях. Возможно воссоздать эту проблему в эмуляторе, используя следующие шаги:
- Создайте и загрузите эмулятор для более старого API (10 или меньше), который включает в себя API Google
- Извлеките карту памяти из эмулятора:
adb pull /system/framework/com.google.android.maps.jar <destination_folder>
Вы можете закрыть эмулятор, как только вы это сделаете.
- Создайте и загрузите эмулятор для нового API (11 или выше), который включает в себя API Google
- Remount/system в эмуляторе, чтобы вы могли написать ему:
adb remount
- Поместите извлеченные карты в новый эмулятор:
adb push <destination_folder>/com.google.android.maps.jar /system/framework
- Перезагрузите эмулятор. Это должно быть выполнимо
adb reboot
, но это просто повесило эмулятор. Вместо этого вам нужно будет убить определенный процесс, который имеет тот же эффект. В Eclipse/DDMS он будет называться system_process
, и вы можете его убить. В качестве альтернативы вы можете запустить эту команду: adb shell ps | grep system_server | awk '{print $2}' | xargs adb shell kill
- После перезагрузки вы можете использовать эмулятор, как обычно. Запуск любого приложения со встроенной картой Google не удастся.
Этот процесс не является постоянным. Перезапуск эмулятора возвращает его в нормальное рабочее состояние.
Можно обнаружить эту проблему, получив метод KeyHelper.getSignatureFingerprint()
в библиотеке карт посредством отражения и вызвав его - передав PackageManager
и имя вашего пакета в качестве аргументов. Кроме того, вы можете заблокировать ошибку в onCreate()
и загрузить новую активность.
Ответ 3
Я нашел простую работу! Просто создайте в src каталог пакета android\security и разместите MessageDigest.java внутри.
package android.security;
import java.security.NoSuchAlgorithmException;
public class MessageDigest
{
private java.security.MessageDigest instance;
public MessageDigest() {}
private MessageDigest(java.security.MessageDigest instance)
{
this.instance = instance;
}
public static MessageDigest getInstance(String algorithm) throws NoSuchAlgorithmException
{
if (algorithm == null) return null;
try
{
if (algorithm.equals("SHA-1"))
return (MessageDigest) Class.forName("android.security.Sha1MessageDigest").newInstance();
else if (algorithm.equals("MD5"))
return (MessageDigest) Class.forName("android.security.Md5MessageDigest").newInstance();
}
catch (Exception e) {}
return new MessageDigest(java.security.MessageDigest.getInstance(algorithm));
}
public void update(byte[] input)
{
instance.update(input);
}
public byte[] digest()
{
return instance.digest();
}
public byte[] digest(byte[] input)
{
return instance.digest(input);
}
}
Он работает, но может начислять другие исключения из-за того, что карта-библиотека не соответствует версии Android.