Android应用程序项目中依赖库项目的NoClassDefFoundError(使用maven作为构建工具)

时间:2014-07-16 13:21:31

标签: java android maven maven-2 maven-3

我开发了两个Android库项目:项目A(MyBaseA)& 项目B(MyBaseB)

我使用maven作为构建工具, MyBaseA MyBaseB <dependency>

我还有一个Android应用程序项目,它使用内置的 MyBaseB.jar 作为库,此jar被添加到Android应用程序项目的构建路径中。

对于库项目A ,pom.xml中的maven坐标定义为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.my.base.a</groupId>
    <artifactId>MyBaseA</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
    <name>MyBaseA</name>
    ...

对于依赖于库项目A 项目的库项目B pom.xml 是:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.my.base.b</groupId>
    <artifactId>MyBaseB</artifactId>
    <version>1.0</version>
    <packaging>apklib</packaging>
    <name>MyBaseB</name>

    <dependencies>
      <!--include library project A as dependency-->
      <dependency>
            <groupId>com.my.base.a</groupId>
            <artifactId>MyBaseA</artifactId>
            <version>1.0</version>
       </dependency>
      ...
   </dependencies>

mvn clean install图书馆计划 A &amp; B 都是成功的。

项目B target/目录下,有 MyBaseB.ap _ MyBaseB.apklib &amp; MyBaseB.jar 文件。

此时,我创建了一个新的Android应用程序项目,其中我将上面的 MyBaseB.jar 包含到我的新Android应用程序项目的构建路径中,并使用了 MyBaseB 项目,它又调用 MyBaseA 项目中定义的函数。

但是当我运行我的新Android应用程序项目时,我得到了例外:

java.lang.NoClassDefFoundError: com.my.base.a.ProjectAClass

我的Android应用找不到项目A 中定义的java类。然后我检查了 MyBaseB.jar 的内容, MyBaseB.jar 中包含库项目A 的所有类 >。为什么?我认为 MyBaseB.jar 应该包含项目A 类,因为pom已将项目A 包含为<dependency>。为什么会发生这种错误?

====================更新=====================

我将库项目<packaging>部分pom从 jar 更改为 apklib ,然后添加项目B(MyBaseB)依赖项中的<type>apklib</type>

  <dependency>
        <groupId>com.my.base.a</groupId>
        <artifactId>MyBaseA</artifactId>
        <version>1.0</version>
        <type>apklib</type>
   </dependency>

现在 MyBaseB.jar 包含项目A 的类。上面的问题解决了(我检查了 MyBaseB.jar 的内容,现在,它包含项目A 的所有类,之前,它没有&#t;

但新问题在于,当我运行Android应用时,只要实例化了一类项目A ,就会出现java.lang.NoClassDefFoundError。应用到达时的那个:

ProjectAClass projAclass = new ProjectAClass();

我得到了java.lang.NoClassDefFoundError。为什么?为什么即使现在抱怨 MyBaseB.jar 包含ProjectAClass.class。

1 个答案:

答案 0 :(得分:0)

这是因为依赖项仅用于编译您的库。在这种情况下,Maven不会做更多的事情,并且会假设库将与所需的依赖项一起部署。

你想要的是:

  • MyBaseA 库部署到您的库类路径可用的位置(可能因为您在android上进行部署而无法实现,但我还没有真正探讨过这个问题,无法确定) ,或

  • 遮蔽库中的依赖项。

使用 maven-shade-plugin 完成着色,添加 MyBaseB 项目的pom:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.3</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <filters>
                <filter>
                  <!-- Exclude cryptographic signatures from dependencies, 
                       almost always mandatory (can cause security errors otherwise) -->
                  <artifact>*:*</artifact>
                  <excludes>
                    <exclude>META-INF/*.SF</exclude>
                    <exclude>META-INF/*.DSA</exclude>
                    <exclude>META-INF/*.RSA</exclude>
                  </excludes>
                </filter>
              </filters>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

该插件将在最终的über-jar中添加编译范围(默认)以及项目的所有依赖项。

the maven-shade-plugin website上提供了更多详细信息和示例。

希望这有帮助。