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

我在我的android客户端中使用com.nimbusds.jose.crypto库来做一些jwt的东西。

这是我在gradle文件中声明的内容:

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

在api> = 19时一切正常,但是当我在api 16上运行代码时,我得到了这个exception:

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

这有什么问题? 为什么api 16上没有AESENGINE类?

如果你查看nimbus-jose-jwt的dependecy列表,就没有bouncycastle库。 但是,如果您查看源代码,更准确地说是查看com.nimbusds.jose.crypto.bc包,那么您可以看到它使用com.nimbusds.jose.crypto.bc而不将其声明为依赖项。 所以图书馆只是假设有一个bouncycastle存在。

解决方案是手动添加依赖项。 首先,按照链接实现在Android上使用bouncycastle的标准方法。

但是,这并没有解决问题,因为org.bouncycastle.crypto.engines.AESEngine不在其中一个库中。 解决方案是添加一个依赖项:

依赖{compile’org.bouncycastle:bcprov-jdk15on:1.54′}

然后一切都应该工作正常。

概要:

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); } 

您依赖nimbus-jose-jwt没有声明对bouncycastle的依赖,因此如果环境本身不提供bouncycastle版本,则会发生错误。 这种情况发生在API Version 16上。

虽然您可以说,这是库的问题,但很可能是故意这样做的 ,因为Bouncycastle可用于不同的JDK版本。 Bouncycastle项目决定使用不同的工件名称来反映不同的JDK版本,而不是在Bouncycastle版本号中反映它。 这导致依赖关系管理中的问题,因为版本解析器不能识别不同版本实际上是相同的工件(它们在技术上是,因为它们包含一组相同的类)。 并且无法解决版本冲突,因此无法抛出版本解决错误,例如在不兼容的主要版本上。

org.bouncycastle»bcprov-jdk16

org.bouncycastle»bcprov-jdk15

org.bouncycastle»bcprov-jdk14

这可能导致类路径上的多个同时发布的bouncycastle版本,这反过来可能导致不可预测的类加载器行为或不可预测的classNotFound / Symbol未find错误(如果使用旧版本,则需要更新版本)。

解决方案很简单:

在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' 

如果缺少其他库,请尝试识别包含这些类的库(最简单的方法是谷歌),并明确添加它们。

Android操作系统随BouncyCastle一起提供。 在API级别16中,AESE引擎类没有附带Android OS(Android决定稍后发布该类)。因此,它无法find该类。

但是,在编译时此类存在,但在运行时它不存在。在这种情况下,当您需要在API 16或以下使用此类时,您必须使用APK发送该类/ jar。

除了写作

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

你也得写这个

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

这将把这个类的范围从编译时间扩展到APK,这将在所有Android版本中都可用。

注意:您必须使用SpongyCastle而不是BouncyCastle来避免类名冲突。