Android java.lang.NoClassDefFoundError: org.bouncycastle.crypto.engines.AESEngine api 16

Я использую библиотеку com.nimbusds.jose.crypto в моем клиенте android для выполнения некоторых jwt файлов.

Это то, что я объявляю в файле gradle:

    compile 'com.nimbusds:nimbus-jose-jwt:4.23'

Все работает отлично на api >= 19, но когда я запускаю код на api 16, я получаю это исключение:

java.lang.NoClassDefFoundError: org.bouncycastle.crypto.engines.AESEngine.

Какая проблема здесь? Почему класс AESENGINE недоступен на api 16?

Ответ 1

Если вы заглянете в список dependecy nimbus-jose-jwt, то нет библиотеки bouncycastle. Однако, если вы посмотрите на исходный код и точнее в пакет com.nimbusds.jose.crypto.bc, вы увидите, что он использует bouncycastle, не объявляя его как зависимость. Таким образом, библиотека просто предполагает наличие bouncycastle.

Решение состоит в том, чтобы вручную добавлять зависимости. Прежде всего, следуйте ссылке , чтобы реализовать стандартный способ использования bouncycastle на Android.

Однако это не решает проблему, потому что org.bouncycastle.crypto.engines.AESEngine не входит в одну из этих библиотек. Решение состоит в том, чтобы добавить еще одну зависимость:

зависимости {   msgstr " }

Тогда все должно работать нормально.

РЕЗЮМЕ:

gradle зависимости должны выглядеть как:

dependencies {
    compile 'com.nimbusds:nimbus-jose-jwt:4.23'
    compile 'com.madgag.spongycastle:core:1.54.0.0'
    compile 'com.madgag.spongycastle:prov:1.54.0.0'
    compile 'com.madgag.spongycastle:pkix:1.54.0.0'
    compile 'com.madgag.spongycastle:pg:1.54.0.0'
    compile 'org.bouncycastle:bcprov-jdk15on:1.54'
}

и вы должны зарегистрировать java.security.Provider:

static {
    Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}

Ответ 2

Вы зависите от nimbus-jose-jwt не имеет заявленной зависимости от bouncycastle, поэтому возникает ошибка, если среда не предоставляет версию bouncycastle. Это происходит в случае API версии 16.

Хотя вы можете сказать, что это проблема библиотеки, это очень вероятно сделано специально, потому что Bouncycastle доступен для разных версий JDK. Проект Bouncycastle решил использовать разные имена артефактов, чтобы отразить разные версии JDK, а не отражать их в номере версии Bouncycastle. Это приводит к проблемам в управлении зависимостями, поскольку распознаватель версии не распознает разные версии как фактически тот же артефакт (который они технически есть, поскольку они содержат набор тех же классов). И не может разрешить конфликты версий и, следовательно, не может вызывать ошибки разрешения версии, например. на несовместимые основные версии.

org.bouncycastle "bcprov-jdk16

против.

org.bouncycastle "bcprov-jdk15

против.

org.bouncycastle "bcprov-jdk14

Это может привести к нескольким совпадающим версиям bouncycastle на пути к классам, что, в свою очередь, может привести к непредсказуемому поведению загрузчика классов или непредсказуемым ошибкам classNotFound/Symbol, не найденным (если используется старая версия, в то время как требуется более новое).

Решение прост:

Добавьте явно указанную зависимость в файл gradle следующим образом:

dependencies {compile 'org.bouncycastle:bcprov-jdk16:1.46'}

или

// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16
compile group: 'org.bouncycastle', name: 'bcprov-jdk16', version: '1.46'

Если отсутствуют дополнительные библиотеки, попробуйте идентифицировать библиотеку, которая содержит эти классы (проще всего это Google), и добавить их явно.

Ответ 3

Android OS поставляется с уже существующим BouncyCastle. На уровне API 16 класс AESEngine не был отправлен с ОС Android (Android решил отправить этот класс позже). Поэтому он не может найти этот класс.

Однако во время компиляции этот класс присутствует, но во время выполнения это не так. В таких случаях, когда вам нужно использовать этот класс в API 16 или ниже, вы должны отправить этот класс/банку с помощью APK.

Помимо записи

compile "com.madgag.spongycastle:prov:1.54.0.0"

Вы должны написать это также

apk "com.madgag.spongycastle:prov:1.54.0.0"

Это расширит сферу применения этого класса от времени компиляции до APK, и это будет доступно во всех версиях Android.

Примечание. Чтобы избежать конфликтов имен классов, вам придется использовать SpongyCastle вместо BouncyCastle.