Maven系列——构建我的Android项目

本博客为个人原创,转载需在明显位置注明出处

在正式开始本篇文章之前,你需要做一些准备工作,他们是:

  1. android-maven-plugin

  2. android-sdk-deployer

关于android-maven-plugin:我们知道Maven只是一座工厂,真正工作的是plugin,由于Android不同于Java,需要构建aar或者apk包,这就是android-maven-plugin存在的意义。虽说让你准备,并不是说让你预先安装环境什么的,而是需要你先弄清楚android-maven-plugin是干嘛的,再读一读官方文档中的使用引导,待真正使用的时候才不会感觉太陌生而措手不及

关于android-sdk-deployer:在编译项目时需要在pom.xml中配置项目所有的依赖,例如junit、gson、fresco等等。对于一个Android项目,Android SDK的依赖是必须的。我们在Android Studio中编译项目依赖的是我们本机中下载好的SDK,但是用Maven构建时,所有的dependency都会从本地仓库中依赖,如果本地仓库没有再从远程仓库中下载,而这恰恰就是问题,因为Maven中央仓库中Android SDK的最高版本仅为4.1.1(不太清楚Google为什么没有继续上传新版本SDK),现在远远达不到我们编译代码的要求,所以我们就得自己想办法。android-sdk-deployer可以帮助我们将你本机安装的Android SDK整理打包,放入本地Maven仓库,这样我们就可以在项目中依赖任何版本的SDK了。

好了,有了上面两项准备,我们就可以正式开始构建自己的Android项目,为此我创建了一个名为Bomb的工程(点我查看),其中有两个module,一个是app,另一个是bombframe,我们的目标就是构建bombframe,将打好的包上传至远程仓库,并可以在另一个工程里面成功依赖。首先我们来看一下工程目录:

《Maven系列——构建我的Android项目》 Paste_Image.png

咦,为什么有两个pom文件?还记得之前我说过,pom文件也是有继承关系的,在实际项目中,我们一个工程下会有多个module,他们肯定需要公共的插件,公共的依赖,这就是为什么有两个pom文件的原因。工程根目录下的pom文件为父pom,其中定义的是公共的plugin和dependency,而bombframe中的pom为子pom,定义的则是其自身的一些特殊配置,下面我们先从父pom开始介绍,由于配置较多,我分段展示讲解:

    <groupId>com.will4it</groupId>
    <artifactId>bomb-frame-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>bomb-frame-parent</name>

    <modules>
        <module>bombframe</module>
    </modules>

父pom不真正提供构建,它有两个作用,一是将一些公共的配置集中存放,二是mvn命令执行的入口,所以packaging不是具体的打包类型,而是pom,你只需记住所有的父pom文件的packaging都是pom就行。另外就是modules,大家应该可以看的明白,这里面定义的是所有的子项目,将需要构建的所有module子项目配置上即可。(这里配置的子项目名是AS工程的module名,跟子pom文件里面的name没关系哈,至少一开始我是这么错误的认为的,结果走了弯路)

<properties>
    <android.maven.plugin.version>4.4.3</android.maven.plugin.version>
    <compiler.version>3.1</compiler.version>
    <javadoc.version>2.9.1</javadoc.version>
    <android.sdk.path>/Users/mowei/Documents/Software/adt-bundle-mac-x86_64-20140321/sdk
    </android.sdk.path>
    <android.sdk.version>21</android.sdk.version>
</properties>

properties我就不多说了,大家复制粘贴就行,将定义的值修改成适合你项目的就行

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>android</groupId>
            <artifactId>android</artifactI
            <version>5.1.1_r2</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

这里要强调一下,作为父pom,在定义公共dependency的时候,最外层需要加上一层dependencyManagement,没有为什么记住就行。另外这里只定义了一个dependency,就是我们的Android SDK,是通过上述android-sdk-deployer生成的。细心的童鞋应该可以发现groupId和version有点不太对劲,是的,我估计android-sdk-deployer的作者是为了跟Maven中央仓库的SDK做个区分。

    <build>
        <plugins>
            <plugin>
                <groupId>com.simpligility.maven.plugins</groupId>
                <artifactId>android-maven-plugin</artifactId>
                <version>${android.maven.plugin.version}</version>
                <extensions>true</extensions>
                <configuration>
                    <failOnNonStandardStructure>false</failOnNonStandardStructure>
                    <sdk>
                        <path>${android.sdk.path}</path>
                        <platform>${android.sdk.version}</platform>
                    </sdk>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${compiler.version}</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

接着就是构建这个工程需要的公共plugin,第一个就是让大家准备的android-maven-plugin,需要解释的是configuration标签,这里面是针对plugin做一些配置的更改。failOnNonStandardStructure的意思是在发现工程结构有错误的情况下不终止不报错,可以翻看一下Maven系列第一篇文章,一开始我就介绍了Maven构建对工程目录的要求,里面有一个resource目录,在我们Android Studio工程中默认是不存在的,但是Maven会严格检查工程结构,一旦不是标准结构就会终止构建并且报错,failOnNonStandardStructure就是为了跳过这一项。第二个是java compiler plugin,没有什么难理解的东西,就是配置JDK的版本和编码格式。

<distributionManagement>
    <repository>
        <id>releases</id>
        <url>你的远程release仓库地址</url>
    </repository>
    <snapshotRepository>
        <id>snapshots</id>
        <url>你的远程snapshot仓库地址</url       >
    </snapshotRepository>
</distributionManagement>

最后一段配置就是你的远程仓库的地址,光看配置没什么难理解的,之前给大家解释过snapshot和release的区别,就连仓库地址也是区分开的,这就是专业、标准。另外,上传到远程仓库是需要用户名和密码的,这个就需要/.m2/settings.xml文件来管理了,在我看来这个问题比较简单,咨询一下度娘你可以搞的定,如果你搞不定,可以给我评论,最后我统计一下人数,如果人数比较多,我会再写一篇文章专门讲解settings文件的配置使用。

以上就是父pom文件的配置,虽然有点长,但是分析下来还是不难的,只要你够耐心够细心,这些都不是问题。下面我们继续看子pom:

<groupId>com.will4it</groupId>
<artifactId>BombFrame</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>aar</packaging>
<name>BombFrame</name>

<parent>
    <groupId>com.will4it</groupId>
    <artifactId>bomb-frame-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
</parent>

在子pom文件中,我们就可以定义packaging为对应的打包类型,这里我们需要构建的是aar包。另外,虽然pom也是继承关系,但是这种继承关系并不像Java代码那么智能,需要手动制定自己的parent是谁,还需要制定父pom文件的路径,这里大家注意一下即可

<properties>
    <keystore>bomb_keystore.jks</keystore>
    <key.store.password>bomb123456</key.store.password>
    <key.alias>bomb</key.alias>
    <key.alias.password>bomb123456</key.alias.password>
</properties>

依然只是properties的定义,这里基本上都是用于签名的keystore信息,下面jarsigner plugin里面需要

<dependencies>
    <dependency>
        <groupId>android</groupId>
        <artifactId>android</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>

这里还需注意,虽然父pom文件中已经定义了Android SDK的依赖,但是子pom中还得重新指定一次,只是version不需要指定,对于dependency,父pom定义的作用主要是统一使用的version,所以子pom中还得再指定一次,如果version不指定,默认就是使用父pom中的版本,如果指定了就使用指定的版本。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jarsigner-plugin</artifactId>
            <version>1.4</version>
            <executions>
                <execution>
                    <id>signing</id>
                    <goals>
                        <goal>sign</goal>
                    </goals>
                    <phase>package</phase>
                    <inherited>true</inherited>
                    <configuration>
                        <includes>
                            <include>target/*.aar</include>
                        </includes>
                        <keystore>${keystore}</keystore>
                        <storepass>${key.store.password}</storepass>
                        <keypass>${key.alias.password}</keypass>
                        <alias>${key.alias}</alias>
                        <arguments>
                            <argument>-sigalg</argument>
                            <argument>MD5withRSA</argument>
                            <argument>-digestalg</argument>
                            <argument>SHA1</argument>
                        </arguments>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

对于plugin就不需要重复指定了,除非是该module独有的plugin,就像这里的jarsigner plugin一样,在打包成功之后,我们需要对aar包进行签名,这里配置的都是一些签名相关信息。

ok,到这里,我们的配置就结束了,在真正执行命令之前,再给大家详细解释一下以下几个常用命令的含义:

mvn package:在需要打包的项目或者module的pom文件相同目录下,创建一个target文件夹,然后执行编译构建打包操作,最后将打好的包等所有相关文件都存入target文件夹中

mvn clean:参考package命令,clean的作用就是删除整个target文件夹

mvn install:在package的基础上,再将打好的包存入本地的Maven仓库

mvn deploy:在install的基础上,将打好的包和pom文件等上传至远程仓库中

清楚这些命令的作用之后,我们就一起来试试看:

~$mvn clean

~$mvn package

如果你的配置没有问题,你会看到:

《Maven系列——构建我的Android项目》 mvn clean
《Maven系列——构建我的Android项目》 mvn package

查看一下module根目录,多了一个target文件夹,里面装着Maven构建好的文件,要啥有啥:

《Maven系列——构建我的Android项目》 target

接着继续敲命令:

~$mvn install

运行结果就不贴了哈,运行成功以后,咱们来看看打好的包有没有装进Maven本地仓库:

《Maven系列——构建我的Android项目》 local repository

特别注意我标记的三个红框哈,从左到右他们分别是groupId,artifactId和version

最后上传到远程仓库去,还记得第一篇文章的最后让大家先注册好Maven中央仓库的账号嘛,这时候就派上用场了

~$mvn deploy

上传成功,我们另外新建一个AS工程,注意这里是新工程而不是新的module哈,然后在新工程gradle中compile ‘com.will4it:bombframe:1.0.0-SNAPSHOT’来依赖看看:

《Maven系列——构建我的Android项目》 gradle config

如图,在依赖的时候你需要做两项配置,一个是配置maven仓库的地址,就是图中repository中的url,为什么?因为gradle默认是从jcenter中寻找依赖包的,上面我们打的包是放在Maven中央仓库或者公司私服仓库的,所以你需要告诉gradle还需要访问哪些仓库地址,这样gradle才能帮你找到;另一个就是compile ‘groupId:artifactId:version’了,不解释。来看看结果吧

《Maven系列——构建我的Android项目》 gradle result

至此,Maven系列文章就结束了,希望我的分享能够帮助到你,一定要动手自己操作。时间有限能力一般,文章中可能有些问题我没说清楚或者理解错的,欢迎大家踊跃拍砖!

注:可能你还会有疑问,我们的代码是需要混淆的,Maven好像是支持javadoc的生成的?经过这四篇文章的学习练习,相信你应该有这个能力自己去摸索

    原文作者:will4it
    原文地址: https://www.jianshu.com/p/1137841cb718
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞