使用Gradle与Ant实现可配置不同环境的自动打包
2016-05-13 22:00
609 查看
一、搭建jenkins环境和配置gradle环境
网上搭建jenkins的教程很多,这里不再赘述,主要说下jenkins中配置gradle环境
点击“Manage Jenkins”
1、 在“Manage Plugins”中搜索并安装gradle插件
2、 在“Configure System”中配置指向你电脑中gradle所在路径(这步前当然要下载gradle)
二、新建jenkins项目并设置构建gradle配置项
1、点击new item新建一个jenkins项目
2、设置构建配置项
a、配置svn代码所在目录
b、配置执行gradle命令(【注意】只有在jenkins中下载安装 了gradle插件后,在”Build”构建项中点击”Add build step”增加构建步骤中看到“Invoke Gradle script”调用gradle脚本)
如上几步后能实现gradle最基本的打包(输出apk的路径app/build/outputs/apk/xxxx.apk)
三、配置ant脚本修改与环境相关的配置项代码(修改jenkins的项目源码)
根据网上搜索的资料,可以在build.gradle脚本的task中修改项目中.java代码,但并没看到大量修改源码并很方便的做法;对于目前所在项目组打包中修改多次环境相关的源代码,还是用ant来专门处理修改源码,两种方式:
1、jenkin的”Add build step”中可以先调用”Invoke Ant”然后”Invoke Gradle script”
2、build.gradle中导入ant脚本(此方法缺点就是不能在”Invoke Ant”的Properties中动态修改源码)
ant脚修改源码步骤如下:
a、AppConfig .java源码
b、before-gradle.xml脚本
c、jenkins中配置。
==> 以上几步可以将isTest设为false,isDebug设为false,执行构建后能出来相应代码配置的apk
五、外部导入签名文件
专门新建一个文件存放签名有关的keystore所在路径和签名密码,据说酱紫比较安全。。
1、build.gradle中
2、signing.properties中。项目目录下新建该文件
六、多渠道打包
1、AndroidManifest.xml
2、build.gradle
a、方式一:
a、方式二:
3、打包命令
电脑中配置了gradle环境变量
1、gradle clean build -b ./build.gradle构建所有包
2、gradle assembleRelease构建所有渠道发布包
3、gradle assemble[xxx]Release构建单个渠道发布包。
如:gradle assembleXiaomiRelease或gradle assembleGooglepalyRelease等和渠道名相关的release命令
4、查看渠道是否随配置更改。查看在下图目录中AndroidManifest.xml中CHANNEL_ID的值xiaomi / googleplay
5、复制apk到目录下apks目录。因为上面release出来的包层级过深,不方便测试人员在jenkins上查找下载apk,所有此步将./app/build/outputs/apk下所有的xx.apk放到DemoProject下的apks目录
完整的build.gradle脚本
gradle在多渠道打包下超有优势,完爆ant;如上脚本gradle打了2个包在哥mac上只需要35-50s,纯ant脚本打一个包2min。。。
问题解决:
1、
Could not resolve all dependencies for configuration ‘:classpath’.
Could not resolve com.android.tools.build:gradle:1.5.0.
Required by:
:DemoProject: unspecified
Could not GET ‘https://jcenter.bintray.com/com/android/tools/build/gradle/1.5.0/gradle-1.5.0.pom‘.
Connection to https://jcenter.bintray.com refused
解决方案就是:降低代码中要求的版本classpath ‘com.android.tools.build:gradle:1.3.0’
2、gradle编译速度超慢
命令行中加–offline。如:gradle assemble - -offline,gradle clean - -offline
gradle-tool是执行gradle的bin目录下gradle工具(window是gradle.bat,unix系统的是gradle)
参考:
1、http://doc.okbase.net/tanlon/archive/125036.html
2、http://www.jianshu.com/p/aa7f93d29805
3、多渠道打包:http://mp.weixin.qq.com/s?__biz=MzI4MzE2MTQ5Mw==&mid=402123825&idx=1&sn=404bdcfd65b6da9a9058260a753b6b55#rd
4、完整脚本:https://github.com/WuXiaolong/Gradle4Android
5、gradle系列:http://gold.xitu.io/#/tag/gradle
6、http://blog.csdn.net/shanlianting/article/details/49820607
7、/article/2636856.html
8、《Gradle构建编译速度太慢的解决方法》http://www.52codes.net/article/658.html
网上搭建jenkins的教程很多,这里不再赘述,主要说下jenkins中配置gradle环境
点击“Manage Jenkins”
1、 在“Manage Plugins”中搜索并安装gradle插件
2、 在“Configure System”中配置指向你电脑中gradle所在路径(这步前当然要下载gradle)
二、新建jenkins项目并设置构建gradle配置项
1、点击new item新建一个jenkins项目
2、设置构建配置项
a、配置svn代码所在目录
b、配置执行gradle命令(【注意】只有在jenkins中下载安装 了gradle插件后,在”Build”构建项中点击”Add build step”增加构建步骤中看到“Invoke Gradle script”调用gradle脚本)
如上几步后能实现gradle最基本的打包(输出apk的路径app/build/outputs/apk/xxxx.apk)
三、配置ant脚本修改与环境相关的配置项代码(修改jenkins的项目源码)
根据网上搜索的资料,可以在build.gradle脚本的task中修改项目中.java代码,但并没看到大量修改源码并很方便的做法;对于目前所在项目组打包中修改多次环境相关的源代码,还是用ant来专门处理修改源码,两种方式:
1、jenkin的”Add build step”中可以先调用”Invoke Ant”然后”Invoke Gradle script”
2、build.gradle中导入ant脚本(此方法缺点就是不能在”Invoke Ant”的Properties中动态修改源码)
ant.importBuild '../power-gradle.xml'
ant脚修改源码步骤如下:
a、AppConfig .java源码
package com.demo.project; public class AppConfig { /** * * 是否打开调试 */ public static boolean isDebug = true; /** * 配置是否用于测试 */ public static boolean isTest = true; }
b、before-gradle.xml脚本
<?xml version="1.0" encoding="UTF-8"?> <project name="DemoProject" basedir="." default="release"> <!--《一》、 start 项目源代码目录 --> <property name="src" value="app/src" /> <property name="res" value="app/src/main/res" /> <!--《一》、end 项目源代码目录 --> <!--《二》、start 文件修改涉及到的文件名称及路径声明 --> <property name="AppConfig" value="${src}/main/java/com/demo/project/AppConfig.java" /> <!--《二》、 end 文件修改涉及到的文件名称及路径声明 --> <!--《三》、start 在Jenkins中Ant属性Properties根据需求来配置不同值 --> <!-- 1、AppConfig文件 --> <!-- isDebug,默认false--> <property name="isDebug" value="false" /> <property name="isDebug-pattern" value="isDebug( )*=( )*.*"></property> <property name="replace-isDebug-pattern" value="isDebug = ${isDebug};" /> <!-- isTest,默认true --> <property name="isTest" value="true" /> <property name="isTest-pattern" value="isTest( )*=( )*.*"></property> <property name="replace-isTest-pattern" value="isTest = ${isTest};" /> <!--《三》、end 在Jenkins中Ant属性Properties根据需求来配置不同值 --> <target name="init"> <echo> 1、setting AppConfig file accord ant Properties</echo> <!-- 关闭debug --> <echo>replace isDebug to ${isDebug}</echo> <replaceregexp file="${AppConfig}" match="${isDebug-pattern}" replace="${replace-isDebug-pattern}" byline="true" flags="gs" encoding="utf-8" /> <!-- 是否可以选择环境--> <echo>replace isTest to ${isTest}</echo> <replaceregexp file="${AppConfig}" match="${isTest-pattern}" replace="${replace-isTest-pattern}" byline="true" flags="gs" encoding="utf-8" /> </target> <target name="release" depends="init"> <echo>ant prepare for release</echo> </target> </project>
c、jenkins中配置。
==> 以上几步可以将isTest设为false,isDebug设为false,执行构建后能出来相应代码配置的apk
五、外部导入签名文件
专门新建一个文件存放签名有关的keystore所在路径和签名密码,据说酱紫比较安全。。
1、build.gradle中
signingConfigs { //外部文件方式导入签名 def Properties props = new Properties() def propFile = new File('signing.properties') if (propsFile.exists() && propFile.canRead()) { props.load(new FileInputStream(propFile)) signingConfigs { release { storeFile file(props['storeFile']) storePassword props['storePassword'] keyAlias props['keyAlias'] keyPassword props['keyPassword'] } } } }
2、signing.properties中。项目目录下新建该文件
//keystore的绝对路径 storeFile=C:\\demo\\project\\demo.keystore storePassword=123456 keyPassword=123456 keyAlias=demo
六、多渠道打包
1、AndroidManifest.xml
<meta-data android:name="CHANNEL_ID" android:value="${CHANNEL_ID_VALUE}"/>
2、build.gradle
a、方式一:
productFlavors {//多渠道打包,命令行打包:gradle assembleRelease xiaomi { // applicationId 'xiaomiRelease' //注释的话,默认xiaomiRelease和xiaomiDebug manifestPlaceholders.put("CHANNEL_ID_VALUE", 'xiaomi') } googlepaly { // applicationId 'googlepalyRelease' //默认googlepalyRelease和googlepalyDebug manifestPlaceholders.put("CHANNEL_ID_VALUE", 'googlepaly') } }
a、方式二:
productFlavors { xiaomi{} googleplay{} productFlavors.all { flavor -> flavor.manifestPlaceholders = [CHANNEL_ID_VALUE: name]//name的值是xiaomi/googleplay } }
3、打包命令
电脑中配置了gradle环境变量
1、gradle clean build -b ./build.gradle构建所有包
2、gradle assembleRelease构建所有渠道发布包
3、gradle assemble[xxx]Release构建单个渠道发布包。
如:gradle assembleXiaomiRelease或gradle assembleGooglepalyRelease等和渠道名相关的release命令
4、查看渠道是否随配置更改。查看在下图目录中AndroidManifest.xml中CHANNEL_ID的值xiaomi / googleplay
5、复制apk到目录下apks目录。因为上面release出来的包层级过深,不方便测试人员在jenkins上查找下载apk,所有此步将./app/build/outputs/apk下所有的xx.apk放到DemoProject下的apks目录
//复制输出apk到项目目录下的apks目录 task copyFiles(type: Copy) { description = 'Copy apks to project directory ./apks ' from 'build/outputs/apk' into './../apks' //因为默认./在app目录 include('**/*') //复制所有 } //根据命令行是构建所有渠道gradle assembleRelease、单个渠道包(如:gradle assembleXiaomiRelease) //还是build构建包。即copyFiles任务是依赖assembleRelease/assembleXiaomiRelease/build assembleRelease.dependsOn copyFiles
完整的build.gradle脚本
apply plugin: 'com.android.application' import java.util.regex.Pattern ////获取详细时间 def buildTime() { return new Date().format("yyyyMMdd'-'HHmm", TimeZone.getDefault()) } //获取日期 def buildDate() { return new Date().format("yyyyMMdd", TimeZone.getDefault()) } android { compileSdkVersion 21 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.demo.project" minSdkVersion 8 targetSdkVersion 8 multiDexEnabled true } sourceSets { main { // manifest.srcFile 'AndroidManifest.xml' // java.srcDirs = ['src'] // resources.srcDirs = ['src'] // aidl.srcDirs = ['src'] // renderscript.srcDirs = ['src'] // res.srcDirs = ['res'] // assets.srcDirs = ['assets'] jniLibs.srcDirs = ['libs'] // 指定jni路径 } } // 签名 signingConfigs { release { // storeFile file('release.keystore') // storePassword '123456' // keyAlias 'demo' // keyPassword '111111' } } buildTypes { release { //是否混淆开关 minifyEnabled false //是否zip对齐 zipAlignEnabled true //是否打开debuggable开关 debuggable false //是否打开jniDebuggable开关 jniDebuggable false //混淆配置文件 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' //签名配置 // signingConfig signingConfigs.release // //release发布版本时针对多渠道。相当于省略多个manifestPlaceholders.put("CHANNEL_ID_VALUE", 'xiaomi') // productFlavors.all { flavor -> // manifestPlaceholders.put("CHANNEL_ID_VALUE", name) //name等于xiaomi / googlepaly // } } } lintOptions {//lint检查,有任何的错误或者警告提示,都会终止构建。false是关闭lint //在打包Release版本的时候进行检测,可以打开,这样报错还会显示出来 checkReleaseBuilds false //abortOnError一定要设为false,这样即使有报错也不会停止打包了 abortOnError false } productFlavors {//多渠道打包,命令行打包:gradlew assembleRelease xiaomi { // applicationId 'xiaomiRelease' //注释的话,默认xiaomiRelease和xiaomiDebug manifestPlaceholders.put("CHANNEL_ID_VALUE", 'xiaomi') } googlepaly { // applicationId 'googlepalyRelease' //默认googlepalyRelease和googlepalyDebug manifestPlaceholders.put("CHANNEL_ID_VALUE", 'googlepaly') } } android.applicationVariants.all { variant -> def manifestFile = file("src/main/AndroidManifest.xml") def pattern = Pattern.compile("versionName=\"(.+)\"") def manifestText = manifestFile.getText() def matcher = pattern.matcher(manifestText) matcher.find() //获取versionName def versionName = matcher.group(1) pattern = Pattern.compile("versionCode=\"(.+)\"") matcher = pattern.matcher(manifestText) matcher.find() //获取versionCode def versionCode = matcher.group(1) if (variant.buildType.name.equals('release')) { variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { // def fileName = "gradle4android_v${defaultConfig.versionName}_${releaseTime()}_${variant.flavorName}.apk" def fileName = buildDate() + "/" + applicationId + "-v" + versionName + "-" + variant.name + "-" + buildTime() + "-" + variant.flavorName + ".apk" output.outputFile = new File(outputFile.parent, fileName) } } } else { variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { def fileName = buildDate() + "/" + applicationId + "-v" + versionName + "-" + variant.name + "-" + buildTime() + "-unaligned.apk" output.outputFile = new File(outputFile.parent, fileName) } } } } } //复制输出apk到项目目录下的apks目录 task copyFiles(type: Copy) { description = 'Copy apks to project directory ./apks ' from 'build/outputs/apk' into './../apks' //因为默认'./'在app目录 include('**/*') //复制所有 } //根据命令行是构建所有渠道gradle assembleRelease,单个渠道包(如:gradle assembleXiaomiRelease) //还是build构建包。即copyFiles任务是依赖assembleRelease/assembleXiaomiRelease/build assembleRelease.dependsOn copyFiles dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') }
gradle在多渠道打包下超有优势,完爆ant;如上脚本gradle打了2个包在哥mac上只需要35-50s,纯ant脚本打一个包2min。。。
问题解决:
1、
Could not resolve all dependencies for configuration ‘:classpath’.
Could not resolve com.android.tools.build:gradle:1.5.0.
Required by:
:DemoProject: unspecified
Could not GET ‘https://jcenter.bintray.com/com/android/tools/build/gradle/1.5.0/gradle-1.5.0.pom‘.
Connection to https://jcenter.bintray.com refused
解决方案就是:降低代码中要求的版本classpath ‘com.android.tools.build:gradle:1.3.0’
2、gradle编译速度超慢
命令行中加–offline。如:gradle assemble - -offline,gradle clean - -offline
gradle-tool是执行gradle的bin目录下gradle工具(window是gradle.bat,unix系统的是gradle)
<target name="clean" depends="xxx"> <echo>gradle clean --offline</echo> <exec executable="${gradle-tool}" failonerror="true"> <arg value="clean" /> <arg value="--offline" /> </exec> </target>
参考:
1、http://doc.okbase.net/tanlon/archive/125036.html
2、http://www.jianshu.com/p/aa7f93d29805
3、多渠道打包:http://mp.weixin.qq.com/s?__biz=MzI4MzE2MTQ5Mw==&mid=402123825&idx=1&sn=404bdcfd65b6da9a9058260a753b6b55#rd
4、完整脚本:https://github.com/WuXiaolong/Gradle4Android
5、gradle系列:http://gold.xitu.io/#/tag/gradle
6、http://blog.csdn.net/shanlianting/article/details/49820607
7、/article/2636856.html
8、《Gradle构建编译速度太慢的解决方法》http://www.52codes.net/article/658.html
相关文章推荐
- My97DatePicker显示日期的奇葩问题(后缀.0)
- 团队冲刺第二天
- 位运算
- wampserver配置多个站点
- java中基本变量、对象、对象引用等在堆与栈中存储、按值传递机制、栈中对象共享机制
- Css常用操作——————分类
- 数据库查询条件语法
- Python装饰器学习(九步入门)
- jQuery 事件 - mousedown() 方法
- 【设计模式】:23种设计模式
- CentOS6安装Jenkins
- 网络基础
- H5初体验
- [Objective-C]关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)
- codefores 352 D. Robin Hood
- jboss启动超时问题
- K最近邻(KNN,k-Nearest Neighbor)准确理解
- drbd简单安装与配置
- python string.atof( )函数
- Windows中获取线程起始地址