Подтвердить что ты не робот

Что такое "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)

Что это?

Спасибо заранее.

4b9b3361

Ответ 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.