android studio的maven私服使用配置踩坑实录
2016-06-28 16:52
936 查看
前言:
随着公司项目的不断增大,开发人员的不断增加,仅用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
问题:开发电脑上可以正常打包的命令在jenkins无法正常工作
可以通过很少的配置让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私服第二步:使用artifactory搭建maven私服
参考的实现方式是: 30分钟搭建一个android的私有Maven仓库问题1. 每个module的build.gradle中都要进行配置
设置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_...即可
同一个工程下的module使用相同的groupId,如:com.xiwei.commonlib
在gradle.properties中统一配置每个module的maven版本号,module之间的依赖,版本号直接引用gradle.properties中的变量
在module的build.gradle中,defaultConfig下添加versionName变量,值为gradle.properties中定义的变量
新建artifactory.gradle
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") } } } }
在工程根目录的build.gradle中添加一行
apply from: "artifactory.gradle"
新建deploy脚本:
deploy.sh
#!/bin/sh ./gradlew :$1:clean :$1:assembleRelease :$1:artifactoryPublish
deploy.bat
@echo off gradlew :%1:clean :%1:assembleRelease :%1:artifactoryPublish
问题2. module的依赖关系没有传递
例如:当B依赖A,C在依赖B时要同时添加A的依赖,否则会报ClassNotFoundException原因
使用artifactory进行的deploy时,生成的pom文件([module]/build/publications/aar/pom-default.xml)中未包含依赖信息:dependencies<?xmlversion="1.0" encoding="UTF-8"?> <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.0</modelVersion> <groupId>com.xiwei.commonlib</groupId> <artifactId>lib_xiwei_common</artifactId> <version>1.0.5</version> <packaging>aar</packaging> </project>
我们需要的pom文件应该长成这样:
<?xml version="1.0" encoding="UTF-8"?> <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.0</modelVersion> <groupId>com.xiwei.commonlib</groupId> <artifactId>lib_xiwei_common</artifactId> <version>1.0.5</version> <packaging>aar</packaging> <dependencies> <dependency> <groupId>com.xiwei.commonlib</groupId> <artifactId>lib_statistics</artifactId> <version>1.0.1</version> </dependency> <dependency> <groupId>com.xiwei.commonlib</groupId> <artifactId>lib_framework_image</artifactId> <version>1.0.0</version> </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) } } } } } } } }
问题3. 在windows上deploy时,报错如下:
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
问题4. 使用maven方式依赖的lib升级过于频繁
被依赖的lib修改代码后需要升级或强制刷新dependencies才能生效,添加新功能或修改bug时十分不便原因
使用指定版本或动态版本(如:1.1.+)时,均会产生maven缓存,lib修改后新发布的版本不能及时生效解决方式
开发阶段使用SNAPSHOT版进行发布及依赖问题5. 升级版本,发布时报错
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,用来配置发布的module的版本号,build.gradle在发布时,版本信息从该properties文件中读取(为了方便,key为module的name)新建modify.sh/modify.bat, 在module发布结束后,读取artifactory_version.properties中该module的版本并写入到gradle.properties文件中,更新被依赖的版本号
修改deploy.sh, 发布后调用modify.sh修改被依赖的版本号
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}
总结
通过一步步踩坑、优化,目前实现的效果为:module采用maven的方式进行依赖
使用jenkins进行CI,QA可自助打不同环境的apk包
只需维护artifactory_version.properties这一个文件进行版本管理即可
修改版本信息后,通过调用命令可一键发布所有包,且互相之间的依赖生效
涉及到的文件
整个配置过程中涉及到的文件有:artifactory.gradle
artifactory_version.properties
build.gradle
deploy.sh
modify.sh
deploy.bat
modify.bat
使用方式
module修改后,artifactory_version.properties中对应module及传递依赖的module要进行升级,并将maven_type改为snapshot进行发布测试验收结束后,maven_type改为release进行发布(调用)
发布命令
发布单个module:
mac:
./deploy.sh moduleName
windows:
deploy.bat moduleName
发布当前工程中的所有module:
mac:
./deploy.sh -a
windows:
deploy.bat -a
原文地址:http://blog.csdn.net/cdecde111/article/details/51777170
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories