随着公司项目的不断增大,开发人员的不断增加,仅用git来进行代码管理、在开发的机器上手工打apk包通过IM工具提交给QA进行测试的开发流程已不再合适,效率及规范性急需提高。
经讨论,决定在公司android项目中使用MAVEN + JENKINS + ARTIFACTORY组合来进行开发流程优化
本文主要介绍在android studio上使用maven私服的实践过程及踩过的一些坑,最终配置在 另一篇文章 中贴出。
相关工具的配置不是本文的重点,需要的同学可以通过下面的传送门了解更多:
maven : 一个项目构建管理工具
公共库的module全部发布到公司maven私服中,app通过添加maven依赖的方式使用
maven的更多介绍请看 这里 , Maven官方文档
jenkins: 一种开源的持续集成系统
自动构建打包,通过配置让QA在jenkins上通过点击按钮打各app不同环境的apk包进行测试
jenkins的安装与配置可以参考 这里 , Jenkins官网
artifactory: 一款maven私服构建&管理工具
用来搭建并管理我们的maven私服仓库
artifactory的使用方式参考文档: 30分钟搭建一个android的私有Maven仓库 , 英文原文
MAVEN + JENKINS + ARTIFACTORY整合
可以通过很少的配置让jenkins拉取git上的代码并执行打包的工作,但在实际的配置过程中,发现我们的代码结构并不适合这种方式
我们的代码结构如下如:
---------------------------------------------------------------------
| CommonLib | business1 | business2 |
| lib_module_1 | app_1 | app_1 |
| lib_module_... | app_... | app_... |
| lib_module_n | app_n | app_n |
---------------------------------------------------------------------
公共lib库及不同的业务线分别在不同android studio工程中,git地址不同,module采用相对地址引用的方式进行依赖,jenkins无法进行配置
module的依赖方式改为maven,搭建maven私服
参考的实现方式是: 30分钟搭建一个android的私有Maven仓库
设置packageName、libraryVersion、artifactory配置等
publishing {
publications {
aar(MavenPublication) {
groupId packageName
version = libraryVersion
artifactId project.getName()
// Tell maven to prepare the generated "* .aar" file for publishing
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
}
}
}
做到以下配置后,升级module版本只需维护gradle.properties中的版本号,并在命令行调用./deploy.sh lib_...
即可
subprojects {
//artifactory相关
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
def myGroupId = 'com.xiwei.commonlib'
publishing {
publications {
aar(MavenPublication) {
if (!project.hasProperty('android')){
return
}
def libVersion = "${project.android.defaultConfig.versionName}"
groupId myGroupId
version = libVersion
artifactId project.getName()
// Tell maven to prepare the generated "*.aar" file for publishing
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
}
}
}
}
apply from: "artifactory.gradle"
deploy.sh
#!/bin/sh
./gradlew :$1:clean :$1:assembleRelease :$1:artifactoryPublish
deploy.bat
@echo off
gradlew :%1:clean :%1:assembleRelease :%1:artifactoryPublish
例如:当B依赖A,C在依赖B时要同时添加A的依赖,否则会报ClassNotFoundException
使用artifactory进行的deploy时,生成的pom文件([module]/build/publications/aar/pom-default.xml)中未包含依赖信息:dependencies
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0modelVersion>
<groupId>com.xiwei.commonlibgroupId>
<artifactId>lib_xiwei_commonartifactId>
<version>1.0.5version>
<packaging>aarpackaging>
project>
我们需要的pom文件应该长成这样:
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0modelVersion>
<groupId>com.xiwei.commonlibgroupId>
<artifactId>lib_xiwei_commonartifactId>
<version>1.0.5version>
<packaging>aarpackaging>
<dependencies>
<dependency>
<groupId>com.xiwei.commonlibgroupId>
<artifactId>lib_statisticsartifactId>
<version>1.0.1version>
dependency>
<dependency>
<groupId>com.xiwei.commonlibgroupId>
<artifactId>lib_framework_imageartifactId>
<version>1.0.0version>
dependency>
dependencies>
project>
修改build.gradle中的artifactory配置,原来的配置是
publishing {
publications {
aar(MavenPublication) {
if (!project.hasProperty('android')){
return
}
def libVersion = "${project.android.defaultConfig.versionName}"
groupId myGroupId
version = libVersion
artifactId project.getName()
// Tell maven to prepare the generated "* .aar" file for publishing
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
}
}
}
修改为(修改方式参考 这里 ):
publishing {
publications {
aar(MavenPublication) {
if (!project.hasProperty('android')){
return
}
def libVersion = "${project.android.defaultConfig.versionName}"
groupId myGroupId
version = libVersion
artifactId project.getName()
// Tell maven to prepare the generated "* .aar" file for publishing
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
}
//The publication doesn't know about our dependencies, so we have to manually add them to the pom
pom.withXml {
//Creating additional node for dependencies
def dependenciesNode = asNode().appendNode('dependencies')
//Defining configuration names from which dependencies will be taken (debugCompile or releaseCompile and compile)
def configurationNames = ["releaseCompile", 'compile']
configurationNames.each { configurationName ->
project.configurations.getByName(configurationName).allDependencies.each {
if (it.group != null && it.name != null) {
println it.group + ":" + it.name + "" + it.version + "," + v_lib_framework_http
println("${it.group}:${it.name}:${it.version}:v_lib_framework_http:${v_lib_framework_http}")
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
//If there are any exclusions in dependency
if (it.excludeRules.size() > 0) {
def exclusionsNode = dependencyNode.appendNode('exclusions')
it.excludeRules.each { rule ->
def exclusionNode = exclusionsNode.appendNode('exclusion')
exclusionNode.appendNode('groupId', rule.group)
exclusionNode.appendNode('artifactId', rule.module)
}
}
}
}
}
}
}
}
Execution failed for task ':lib_framework_http:artifactoryPublish'.
> File 'E:\work\CommonLib\lib_framework_http\build\publications\aar\pom-default.xml' does not exist, and need to be published from publication aar
artifactory没有自动调用构建pom的task
deploy脚本: deploy.bat
@echo off
gradlew :%1:clean :%1:assembleRelease :%1:artifactoryPublish
修改后的脚本deploy.bat:
@echo off
gradlew :%1:clean :%1:assembleRelease :%1:generatePomFileForAarPublication :%1:artifactoryPublish
被依赖的lib修改代码后需要升级或强制刷新dependencies才能生效,添加新功能或修改bug时十分不便
使用指定版本或动态版本(如:1.1.+)时,均会产生maven缓存,lib修改后新发布的版本不能及时生效
开发阶段使用SNAPSHOT版进行发布及依赖
Error:Failed to resolve: com.xiwei.commonlib:lib_statistics:1.0.2
为了维护方便,正在发布的module版本号与其它module依赖该module指定的版本号在gradle.properties中为同一个变量,升级发布时,修改了这个变量,执行gradlew命令会检查所有module的dependencies
由于发布尚未开始,maven仓库中并无此版本的module,故而报错
artifactory_version.properties
#发布的类型:snapshot/release
maven_type=snapshot
lib_db=1.0.0
lib_framework_image=1.0.0
...
lib_statistics=1.0.1
lib_xiwei_common=1.0.5
modify.sh
#!/bin/sh
#project的版本定义文件
SOURCE_FILE_NAME="artifactory_version.properties"
#dependencies的版本定义文件
GRADLE_FILE_NAME="gradle.properties"
#从SOURCE_FILE_NAME的key到GRADLE_FILE_NAME的key需要添加的前缀:比如:lib_db -> v_lib_db 前缀为 v_
KEY_PRE_FIX="v_"
function contains
{
STRING_A=$1
STRING_B=$2
if [[ ${STRING_A/${STRING_B}//} == $STRING_A ]]
then
return 0
else
return 1
fi
}
function replace_prop() {
KEY=$1
VALUE=$2
SUFFIX=''
if [[ ${maven_type} = 'snapshot' ]]; then
SUFFIX='-SNAPSHOT'
fi
cat $GRADLE_FILE_NAME | while read LINE
do
contains $LINE "$KEY_PRE_FIX$KEY="
result=$?
if [[ $result = 1 ]]; then
#包含$KEY_PRE_FIX$2=的行内容替换为v_$2=$3
sed -ig "s/$LINE/$KEY_PRE_FIX$KEY=$VALUE$SUFFIX/g" ${GRADLE_FILE_NAME}
rm -f ${GRADLE_FILE_NAME}g
return
fi
done
}
#读取需要拷贝的properties文件
. ${SOURCE_FILE_NAME}
#todo check params
#替换GRADLE_FILE_NAME文件中key为$1的行内容:例如v_lib_db=1.0.0 -> v_lib_db=1.0.1
replace_prop $1 ${!1}
通过一步步踩坑、优化,目前实现的效果为:
整个配置过程中涉及到的文件有:
./deploy.sh moduleName
deploy.bat moduleName
./deploy.sh -a
deploy.bat -a
原文地址:http://blog.csdn.net/cdecde111/article/details/51777170