当Android Studio 3.0遇上Jenkins

来源:互联网 发布:淘宝达人发布短视频 编辑:程序博客网 时间:2024/05/20 08:41


今日快讯


近日有爆料称:多名高中生被学校强迫在富士康郑州工厂实习,采用11小时轮班制,他们每天最多能组装1200个iPhone X摄像头。对此苹果和富士康表示,这些学生是自愿工作的,也获得了报酬和福利。不过,富士康也承认,这些实习生加班工作违反了公司的政策,并且已采取“迅速行动”,从现在起,实习生每天至多工作8小时。


作者简介


明天又是周末啦,提前祝大家周末愉快!

本篇来自 wustor 的投稿,分享了在AS升级成3.0后, 使用持续集成工具jenkins遇到的问题,并给出了解决方案,希望对大家有所帮助 。

wustor 的博客地址:

http://www.jianshu.com/u/94dc45995a85


简介


jenkins 是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。

关于 Android Studio 持续集成的文章已经是满天飞了,不过都是在AS 2.X的环境下面进行集成的,最近升级了AS 3.0之后,发现按照之前的一些方法无法在AS 3.0上顺利集成,本来很简单的几步操作,却调试了很久,下面简单记录一下调试的过程,可以让一部分开发者少走弯路。

本文是基于 GitLab 集成,其余的类似于 Git,SVN 其实原理都一样,稍微有点区别,稍微调试一下就好。


基本知识


简单的Groovy语法

普通标识符:以字母、美元符号$或下划线_开始,不能以数字开始

def date = new Date()

引号标识符:使用单引号括住的字符串

def name = 'android'

括号{}:表示引用;美元符号$:表示拼接

//相当于assembleWandoujiaRelease
assemble${PRODUCT_FLAVOR}${BUILD_TYPE}

基本的gradle命令

说来惭愧,平时都是点击AS的可视化按钮,很少去研究这些命令,直到这次 debug,才发现,命令行在 debug 确实很有用

  • gradlew clean //删除 app目录 下的 build文件

  • gradlew build//编译 debug 跟 release 包

  • gradlew assembleDebug //编译 debug 包

  • gradlew assembleRelease //编译 release 包

jenkins提供的全局变量

这些变量可以在写脚本,包括 gradle脚本 以及 python脚本 的时候可以调用,我们也可以自己通过插件来配置一些变量,用来进行构建不同的渠道包,下面选取了一些常用的:

  • BRANCH_NAME项目分支名称

  • CHANGE_AUTHOR修改项目的作者

  • BUILD_NUMBER构建的序列号

  • JOB_NAME构建的项目名称

  • WORKSPACE: 服务器构建项目的位置

  • JENKINS_HOME: jenkins的根目录

  • GIT_COMMITTER_EMAIL: Git提交作者的邮箱

登陆无效解决方案

当关掉 jenkins 的网页,再重新打开的时候,会让你重新登录,但是当你输入正确的用户名跟密码的时候,却会提示你登陆无效,解决方案如下:

1.找到安装目录下的 config 文件

2. 找到 useSecurity 节点,将true 改为 false

<useSecurity>false</useSecurity>

3.找到 authorizationStrategy 跟 securityRealm 节点,删除这两个节点

4. 重启 jenkins,不知道怎么重启的,直接重启电脑,再次启动 jenkins 即可。

修改build.gradle文件

AS3.0 升级了 gradle,改动较大,对比一下之前的代码,便可以发现区别,主要是在 flavor 的添加时必须增加一个 dimension,apk 输出路径做了较大的修改,为了减少代码量,只贴出了变动的部分

android {     signingConfigs {         config {             keyAlias 'demo'             keyPassword '123456'             storeFile file('chuangmei.jks')             storePassword '123456'             flavorDimensions "versionCode"         }     }     flavorDimensions "market"     productFlavors {         xiaomi {             dimension "market"             manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]         }         wandoujia {             dimension "market"             manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]         }     }     applicationVariants.all { variant ->         variant.outputs.all { output ->             outputFileName = variant.productFlavors[0].name + new Date().format('yyyyMMddHHmmss') + '-' + variant.buildType.name + '.apk'         }     } }

安装jenkins

官网是 https://jenkins.io,有三种安装方式,分别是 war包,native包 以及 docker容器,这里我选择的是 native包,因为这种方式可以帮助我们安装一部分插件,基本上可以满足我们的需求。


配置环境


插件安装

native包安装:基本够用,然后可以根据需求扩展

war包安装:

  • Git plugin

  • Gradle Plugin

  • SSH plugin

这里选择的几个插件貌似能够打出apk,网上有很多文章,会安装很多插件,一来没必要,二来很多插件已经过时了,最新的 jenkins 版本已经不支持,即使是通过本地上传的方式,除非使用较老的 jenkins 版本。

系统设置

设置构建路径

找到主目录,然后点击高级

修改构建路径

理解了 groovy语法,上面的路径就很好理解了,这个是可以随便修改的

设置环境变量

找到全局属性,勾选环境变量,设置SDK路径

设置环境变量

全局工具配置

name 可以随便填,对应的 value 则是相应的路径

JDK路径

Git路径

Gradle路径


项目配置


创建一个项目

名称随便填,这里选择自由风格的软件项目,选择第一个也可以,看自己需求

参数化构建

构建环境

配置相应的构建环境

构建

根据之前设置的条件进行编译操作

构建后操作

主要是可以用来收集构建出来的apk以及相应的编译文件


开始构建


其实最花时间的还是这里,因为,升级了AS 3.0 之后,gradle 的版本变成了 4.1,改动特别大,所以升级要慎重,但是已经升级了,问题还是得解决。

执行 gradle clean assembleRelease

是从这一行代码进行报的错,提示我说是在 release 合并资源的时候报错了,下面是具体的信息

下面最后一行开始报错

:app:generateAndroidReleaseResValues :app:generateAndroidReleaseResources :app:mergeAndroidReleaseResources

然后错误一直不断重复

AAPT err(Facade for 1119711668) : No Delegate set : lost message:\\?\C:\Windows\System32\config\systemprofile\.gradle \caches\transforms-1\files-1.1\appcompat-v7-25.4.0.aar\76d6a769daf730ed767830374ebcd3bd \res\drawable-hdpi-v4\abc_textfield_search_default_mtrl_alpha.9.png ERROR: Unable to open PNG file

追踪堆栈信息 --stacktrace --debug

* What went wrong: 16:04:41.129 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Execution failed for task ':app:mergeAndroidReleaseResources'. 16:04:41.129 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] > Error: java.util.concurrent.ExecutionException: com.android.builder.internal.aapt.AaptException:
16:04:41.129 [ERROR]

对吧,日志都出来了,看地我是一脸懵逼,只看懂了app:mergeAndroidReleaseResources


漫长的Debug之路


环境检查

我的项目在本地是成功编译过的,不管是 debug 还是 release 都是OK的,clean 也是没问题的,所以我当时就觉得应该是服务端编译的问题,但是服务端的代码是从 gitlab 上面获取的,跟我本地的是一模一样的,不应该有问题,难道是编译环境出了问题吗,因为上面的报错都是跟 gradle 相关的,所以我就打印了各自的 gradle:

本地grade版本:

Gradle 4.1 ------------------------------------------------------------ Build time:   2017-08-07 14:38:48 UTC Revision:     941559e020f6c357ebb08d5c67acdb858a3defc2 Groovy:       2.4.11 Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015 JVM:          1.8.0_131 (Oracle Corporation 25.131-b11) OS:           Windows 10 10.0 amd64

服务端grade版本:

Gradle 4.1 ------------------------------------------------------------ Build time:   2017-08-07 14:38:48 UTC Revision:     941559e020f6c357ebb08d5c67acdb858a3defc2 Groovy:       2.4.11 Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015 JVM:          1.8.0_131 (Oracle Corporation 25.131-b11) OS:           Windows 10 10.0 amd64

是一样的,呵呵哒,只能再分析别的原因了,其实这个时候是没有什么思路的,因为太诡异了,基本上什么都一样了,但是服务端就是编译不成功,我能怎么办,我也很绝望啊。然后就用Google搜索了一下,搜到的答案基本上都不是太相关,只好作罢。

目录对比

其实在对比环境之后当时就想着回退版本了,毕竟已经折腾了很久了,不过转念一想,程序员不就是为问题而生的吗,然后又冷静思考了一会儿,还有什么是不一样的,终于发现了,目录,服务端编译的目录跟本地的目录不一样,可是这个在理论上是没有影响的,不过值得一试。然后我就直接打开了服务端在本地的项目,然后进行检查。

gradle clean

本地:

E:\Jenkins\workspace\Test>gradle clean > Configure project :app FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:clean'. > Unable to delete file: E:\Jenkins\workspace\Test\app\build\intermediates\merged-not-compiled-resources\android\release\anim\abc_fade_in.xml

服务端:

[Gradle] - Launching build. [Test] $ cmd.exe /C "C:\Users\pangchao\.gradle\wrapper\dists\gradle-4.1-all\bzyivzo6n839fup2jbap0tjew\gradle-4.1\bin\gradle.bat clean && exit %%ERRORLEVEL%%" :clean :app:clean BUILD SUCCESSFUL in 20s 2 actionable tasks: 2 executed Build step 'Invoke Gradle script' changed build result to SUCCESS

是不是很意外,一个失败一个成功,而且居然是本地失败,服务端成功,很诡异。

gradle assembleRelease

本地打包:

E:\Jenkins\workspace\Test>gradle assembleMumayi > Configure project :app [E:\Jenkins\workspace\Test\app\build\outputs\mapping\mumayi\release\dump.txt]... Removed unused resources: Binary resource data reduced from 559KB to 539KB: Removed 3% BUILD SUCCESSFUL in 31s 51 actionable tasks: 49 executed, 2 up-to-date E:\Jenkins\workspace\Test>

服务端打包:

[Gradle] - Launching build. :app:assembleMumayiRelease :app:assembleMumayi BUILD SUCCESSFUL in 7s 51 actionable tasks: 6 executed, 45 up-to-date Build step 'Invoke Gradle script' changed build result to SUCCESS Finished: SUCCESS

可以看到先由本地编译,然后再经过服务端编译时都可以成功的,但是之前我们是先经过服务端编译时不能成功的,也就是说,我们要先进入到服务端的目录本地成功编译一次之后,才能在服务端成功编译。最重要的一点是服务端打包之间不能进行 clean,具体原因我也不是很清楚,应该是跟 AS 3.0 升级的特性有关系,改天研究一下官方文档才能知道具体原因,也就是说目前的情况如下:

也就是在 AS3.0 的基础上,如果我想在服务端自动构建apk,那么首先必须在本地成功编译一次,既然是这样,那么我们干脆在本地先把所有渠道的 Debug包 Release包 先统一编译一次,这样的话在服务端不管想要打哪种包都是OK的,就这么愉快地决定了。

  • gradlew clean

  • gradlew build

这样就好了,剩余的操作跟之前的 AS 2.X 基本一致,OK,到此为止,AS 3.0 也可以很轻松的使用 jenkins,虽然折腾了很久,但是最终还是解决了问题。


后续


集成过 jenkins 的小伙伴们可能知道,其实还有很多功能没有细说,比如说打完包后将安装包自动上传到fir或者蒲公英,生成一个二维码,发送邮件到指定的收件人,其实这些都比较好解决的,网上已经有很多教程了,而且这些都可以通过插件跟脚本实现,下面贴一下相关的插件,大家Google或者百度一下就可以搞定了,本文主要在于分析一下 AS 3.0 的继承问题,没有针对这些问题进行研究。


欢迎长按下图 -> 识别图中二维码

或者 扫一扫 关注我的公众号

原创粉丝点击