├── README.md
├── build.gradle
├── gradle.properties
├── image
├── image_1.png
├── image_10.png
├── image_11.png
├── image_12.png
├── image_13.png
├── image_14.png
├── image_15.png
├── image_16.png
├── image_17.png
├── image_18.png
├── image_19.png
├── image_2.png
├── image_20.png
├── image_21.png
├── image_22.png
├── image_23.png
├── image_24.png
├── image_25.png
├── image_26.png
├── image_27.png
├── image_28.png
├── image_29.png
├── image_3.png
├── image_4.png
├── image_5.png
├── image_6.png
├── image_7.png
├── image_8.png
└── image_9.png
├── plugins.zip
└── upload.py
/README.md:
--------------------------------------------------------------------------------
1 |
利用Jenkins玩转Android自动打包发包
2 | ### 本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布
3 |
4 | ### 请尊重原创,转载请注明出处:http://blog.csdn.net/mabeijianxi/article/details/52680283
5 | ### 先看一眼效果图:
6 |
7 | 功能描述:可以选择不同的环境与不同的渠道,可以输入显示在App上的版本号,打包完成后可自动上传并且生成安装二维码
8 | 总体步骤可为:
9 |
10 | - 下载新版Jenkins挂载到Tomcat
11 | - 编写Python脚本拉取蒲公英上Apk二维码(可选)
12 | - 配置项目build.gradle里面的脚本
13 | - 安装Jenkins里面需要用到的一些插件并且配置Jenkins参数
14 |
15 | 脚本配置地址:https://github.com/mabeijianxi/android-automation
16 | 正式开撸
17 | 一、下载新版Jenkins挂载到Tomcat:
18 | 到Jenkins下载适合的版本后点击安装,之后在Tomcat的webapps目录下新建一个Jenkins目录,再把刚安装好的Jenkins目录打开找到war目录,拷贝目录下全部数据到webapps下新建的Jenkins目录中。还有种启动方式是通过命令启动jenkins.war就行了,```java -jar jenkins_located_path/jenkins.war```。我们可以先为工作空间配置个环境变量。


19 | 我使用的是第一种方式,再启动Tomcat后访问http://localhost:8080/jenkins就会进入引导进入页面,如果有选择安装插件界面进去后点击安装就行,一会儿就能进入主界面。

20 | 二、安装Jenkins里面需要用到的一些插件:
21 | 这里也没什么技术含量,系统管理->插件管理->管理插件->可选插件:
22 | 勾选如下插件:
23 |
24 | - Branch API Plugin
25 | - build timeout plugin
26 | - build-name-setter
27 | - Credentials Binding Plugin
28 | - description setter plugin
29 | - Dynamic Parameter Plug-in
30 | - Environment Injector Plugin
31 | - fir-plugin(可选)
32 | - Git plugin(可选)
33 | - GIT server Plugin(可选)
34 | - Gradle Plugin
35 | - Pipeline: Basic Steps
36 | - Pipeline: Build Step
37 | - Pipeline: Input Step
38 | - Pipeline: Nodes and Processes
39 | - Pipeline: Stage Step
40 | - Post-Build Script Plug-in
41 | - SSH Slaves plugin
42 | - Subversion Release Manager plugin(可选)
43 | - Timestamper
44 | - Workspace Cleanup Plugin
45 | - Subversion Plug-in(可选)
46 |
47 | 由于有些插件之间有依赖关系所以没全部列出来,如过有我问题可以对比我的截图。


。
48 |
49 | 三、配置build.gradle:
50 | 上面都是枯燥的准备工作,好玩的才刚刚开始,下面的参数传入很有意思,也是我踩了很多坑以后想到的。
51 | 进入Android Studio->打开主Module的build.gradle:
52 |
53 | - 配置签名信息,不然打的包就没意义了
54 | - 以参数化构建你想动态写入的数据。我自己需要动态写入的参数有versionName、打包时间戳、是来自Jenkjins运行还是我们本地打包的标识符,这里很重要,如果是来自Jenkins打包那么我们的生成路径肯定是服务器上的路径,否则是我们本地电脑上的路径。把这三个参数与其在本地的默认值定义在gradle.properties中,然后在build.gradle变能引用。
55 | - 动态修改生成的Apk路径与名称,因为如果是Jenkins打包发包那么名称必须是Jenkins传递过来的,不能写死,且唯一,不然没法上传
56 |
57 | 废话不多说,程序员就哪需要看这么多文字,直接干代码(一下是项目中部分代码):
58 |
59 |
60 | ```
61 | gradle.build:
62 |
63 | def getDate() {
64 | def date = new Date()
65 | def formattedDate = date.format('yyyyMMddHHmm')
66 | return formattedDate
67 | }
68 | def verCode = 14
69 | android {
70 | compileSdkVersion 22
71 | buildToolsVersion "23.0.3"
72 | signingConfigs {
73 | signingConfig {
74 | keyAlias 'xxx'
75 | keyPassword 'xxx'
76 | storeFile file('xxx')
77 | storePassword 'xxx'
78 | }
79 | }
80 |
81 | defaultConfig {
82 | applicationId "com.henanjianye.soon.communityo2o"
83 | minSdkVersion 14
84 | targetSdkVersion 22
85 | multiDexEnabled true
86 | versionCode verCode
87 | versionName APP_VERSION
88 | resValue("string", 'app_version', APP_VERSION)
89 | buildConfigField "boolean", "LEO_DEBUG", "true"
90 | buildConfigField 'String', 'API_SERVER_URL', RELEASE_API_SERVER_URL
91 | buildConfigField 'String', 'API_SERVER_URL_MALL', RELEASE_API_SERVER_URL_MALL
92 | signingConfig signingConfigs.signingConfig
93 | }
94 | buildTypes {
95 | release {
96 | buildConfigField 'String', 'API_SERVER_URL', RELEASE_API_SERVER_URL
97 | buildConfigField 'String', 'API_SERVER_URL_MALL', RELEASE_API_SERVER_URL_MALL
98 | buildConfigField 'String', 'IM_SERVER_HOST', RELEASE_IM_SERVER_HOST
99 | buildConfigField 'int', 'IM_SERVER_PORT', RELEASE_IM_SERVER_PORT
100 | buildConfigField "boolean", "LEO_DEBUG", RELEASE_LEO_DEBUG
101 | minifyEnabled true
102 | zipAlignEnabled true
103 | shrinkResources true
104 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
105 | }
106 | debug {
107 | buildConfigField 'String', 'API_SERVER_URL', RELEASE_API_SERVER_URL
108 | buildConfigField 'String', 'API_SERVER_URL_MALL', RELEASE_API_SERVER_URL_MALL
109 | buildConfigField 'String', 'IM_SERVER_HOST', RELEASE_IM_SERVER_HOST
110 | buildConfigField 'int', 'IM_SERVER_PORT', RELEASE_IM_SERVER_PORT
111 | buildConfigField "boolean", "LEO_DEBUG", RELEASE_LEO_DEBUG
112 | }
113 | }
114 | dexOptions {
115 | javaMaxHeapSize "2g"
116 | }
117 |
118 |
119 | //渠道Flavors,我这里写了一些常用的
120 | productFlavors {
121 | commonsoon {
122 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "commonsoon"]
123 | }
124 | zhushou91 {
125 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "zhushou91"]
126 | }
127 | }
128 | allprojects {
129 | repositories {
130 | mavenCentral()
131 | maven { url "https://jitpack.io" }
132 | }
133 | }
134 | //修改生成的apk名字
135 | applicationVariants.all { variant ->
136 | variant.outputs.each { output ->
137 | def newName
138 | def timeNow
139 | def oldFile = output.outputFile
140 | def outDirectory = oldFile.parent
141 |
142 | if ("true".equals(IS_JENKINS)) {
143 | timeNow = JENKINS_TIME
144 | outDirectory = 'G:/Tomcat/webapps/jenkins/apk'
145 | newName = 'yj-android-v' +
146 | APP_VERSION + '-' + variant.productFlavors[0].name + timeNow + '-' + variant.buildType.name + '.apk'
147 | } else {
148 | timeNow = getDate()
149 | if (variant.buildType.name.equals('debug')) {
150 | newName = "yj-android-v${APP_VERSION}-debug.apk"
151 | } else {
152 | newName = 'yj-android-v' +
153 | APP_VERSION + '-' + variant.productFlavors[0].name + timeNow + '-' + variant.buildType.name + '.apk'
154 | }
155 | }
156 |
157 | output.outputFile = new File(outDirectory, newName)
158 |
159 | }
160 | }
161 | }
162 |
163 |
164 | gradle.properties:
165 |
166 |
167 | RELEASE_API_SERVER_URL="xxx"
168 | RELEASE_API_SERVER_URL_MALL="xxx"
169 | RELEASE_IM_SERVER_HOST="xxx"
170 | RELEASE_IM_SERVER_PORT=5222
171 | RELEASE_LEO_DEBUG=false
172 |
173 | INSIDE_TEST_API_SERVER_URL="xxx"
174 | INSIDE_TEST_API_SERVER_URL_MALL="xxx"
175 | INSIDE_TEST_IM_SERVER_HOST="xxx"
176 | INSIDE_TEST_IM_SERVER_PORT=5222
177 | INSIDE_TEST_LEO_DEBUG=true
178 |
179 | APP_VERSION=2.4.0
180 | IS_JENKINS=false
181 | JENKINS_TIME=''
182 |
183 | ```
184 |
185 | 四、配置Jenkins参数
186 | 回到主界面->系统管理->Global Tool Configuration:
187 | 配置好JDK与Gradle。由于我本地已安装好JDK与Gradle所以只需为其指定路径即可。


188 | 然后回到主界面->新建->构建一个自由风格的项目->ok:
189 |
190 | - 勾选上参数化构建过程,先点击Choice可为其配置可选参数。我的项目需要配置的可选参数有API环境、打包渠道、是否来自Jenkins打包的标识。
191 | 



192 | - 点击String Parameter,让使用者可以自定义显示在App上的版本号,方便测试。可以再添加一个可输入的标签,最后把这个标签加到构建页的构建名称中。

193 | - 点击Dynamic Parameter,注入Groovy脚本,主要是生成时间戳。

194 | - 如果是SVN用户可选择List SubVersion tags,然后写地址帐号密码等,这个选项可以让你选择打包SVN上不同版本的代码。如果是Git用户可参照http://birdinroom.blog.51cto.com/7740375/1404930 上面的配置来拉取不同的版本。


195 | - 勾选源码管理中自己所用的管理工具Git或者Subversion,填写好相关信息,当然我们的地址是动态的,所以需要引用上一步所选择的版本,如图。(如果是Linux后面得加上/,不然拉取的其目录下的内容不包含TAG_SVN这个目录)

196 | - 在构建环境中勾选上Set Build Name,主要是动态生成每次显示在构建页上的名称方便查看。

197 | - 在构建栏里面选择Invoke Gradle Script->选择配置好的Gradle Version->在Tasks中输入Gradle命令(没了解过的建议先看下Gradle的基本命令),我们先执行一个clean,然后开始编译,这时候就可以用引用上面配置的一些参数了,这里可以用-P命令把参数传入,也可以更方便的把下面的Pass jod parameters as Gradle properties勾选上,其实内部也是用-Pkey=Value的命令->在Root Build script中动态指定你项目的目录,为什么是动态的呢?这是因为我们上面提供了可选版本的功能,所以拉取的每个版本所放目录是不一样的,想要编译相应的版本就得动态指定编译目录。
198 | - 上面的操作如果成功那么其实这时候构建已经可以在build.gradle所配置的输出路径中找到相应的Apk了,但是这还不够酷,我想把生成的Apk放到托管平台,一般用fir.im与蒲公英。如果选择fir.im那么本步骤略过,我个人推荐蒲公英,因为其可用命令行上传比较方(装)便(B)。下面是蒲公英上传的步骤。
199 | 1)简单的实现方式:参照官方文档https://www.pgyer.com/doc/view/jenkins 。这种方式可以可以简单的通过命令行上传,方便使用,且后续可以动态拿到Apk的下载连接,与最新版本的二维码。但是想要拿到每个版本的二维码确实不行的。其实上传成功后返回的json数据中Apk的下载地址与二维码地址是写死的一个短网址,后续说明解决办法。这里按照官方的步骤,如果是Linux
200 | 那么在增加构建步骤中选择Execute Shell,而Windows环境的需要先下载curl工具,然后选择Execute Windows batch command。get地址与使用方法都在里面http://www.2cto.com/os/201205/131164.html 。

201 | 需要注意这里的上传文件的名称也是动态引用的方式,因为每次生成的名称是唯一的。如果是Shell那么引用方式是${NAME},而batch引用方式是%NAME%。
202 | 2)比较装逼的方式:我不只想要每个版本的下载长链接,我还想要每个版本二维码的长链接。但是就算通过浏览器打开最新上传的Apk地址,里面的二维码也只有短链接,不管是Apk的短链接还是二维码的它们其实是写死的,永远指向最新版的地址,这就有个问题,当在Jenkins中打开非最新版本的Apk地址或者二维码图片地址那么都会指向最新的,这就比较蛋疼了。经过仔细观察发现蒲公英Apk长链接生成的规则其实是固定字符串+appKey。Apk在返回的json串中可以找到。于是可以利用python脚本来执行上传,然后正则配置到AppKey,然后再拼上静态字符串就拿到了本次存放Apk的长链接。当然如果只是为了Apk安装长链接用第一种方式即可。现在需要的是二维码的长链接,用Apk的长链接发起Http请求然后就可以拿到页面数据,通过正则匹配可以匹配到里面二维码的img标签地址,但是是短地址,蒲公英只有非最新Apk才会在这个页面的img标签中返回长地址。于是我打了一个包名与签名同上传Apk相同的Apk,里面没东西,大小只有几十K。在第一个Apk上传完成后马上上传这个小的Apk,这样再去拉取页面里面的img标签就可以得到二维码的长网址了。具体实现看下面python代码。
203 |
204 | #coding: utf-8
205 | import os
206 | import re
207 | import requests
208 | import sys
209 |
210 | if len(sys.argv) == 2:
211 | mainpath = sys.argv[-1]
212 | else:
213 | exit()
214 |
215 | temppath = r'G:\mydownload\GETUI_ANDROID_SDK\GETUI_ANDROID_SDK\Demo\PushDemo\yijia\temp.apk'
216 |
217 | cmd = 'curl -F "file=@{path}" -F "uKey=xxx" -F "_api_key=xxx" http://www.pgyer.com/apiv1/app/upload'
218 | content = os.popen(cmd.format(path=mainpath)).read()
219 | print(content)
220 |
221 | match = re.search('"appKey":"(\w+)"', content)
222 |
223 | if match:
224 | appkey = match.group(1)
225 |
226 | content = os.popen(cmd.format(path=temppath)).read()
227 |
228 | url = 'http://static.pgyer.com/' + appkey
229 | html = requests.get(url).text
230 |
231 | match = re.search('http://static.pgyer.com/app/qrcodeHistory/\w+', html)
232 | if match:
233 | print('appKey#{soonAppkey}#appKeysoon#{soon}#soon'.format(soonAppkey=appkey,soon=match.group()))
234 | else:
235 | print('no qrcode')
236 |
237 | 命令中执行如图代码:
238 |
239 | - 经过上面的操作后大业马上就成了,接下来就是收集成果的时候了,在增加构建后操作步骤中选择Set build description,在Regular expression中填写正则,然后Description中可以引用,这里去匹配的是构建日志中的内容,Description的内容将显示到构建页面。我们这里如果需要插入下载链接或者二维码的话那么就需要用到Html标签,这时候需要去先设置下。步骤:系统管理->Configure Global Security-> Markup Formatter->Safe HTML。如果是选择上面的简单实现方式那么Regular expression的正则可以用:"appKey":"(.*)","userKey",如果用我的pyhton脚本上传,那么正则可以是:appKey#(.*)#appKeysoon#(.*)#soon,然后在Description中通过\1或者\2引用即可。


240 |
241 | 四、打包喝咖啡
242 | 到这里那么最感动的时刻来了,轻轻的点击下保存按钮,这时候你会来到构建界面,轻击 Build with Parameters,就会出现这个界面

配置好参数,按下时代性的构建。从这一刻起谁向你要包你可以点根烟淡淡的说道:妈的,撸着呢,一边自己打去。我反正是受够了要包岁月。
243 | 注意事项:
244 | 1、参数传递的时候Jenkins里面的参数名称需要与build.gradle里面的一致,不然没什么卵用。如:


245 | 2、在Linux下需要注意一些编译工具的权限问题,如aapt。
246 | 3、在服务器上的SDK最好与你本地的一致,不然指不定编译的时候会少东西。如果服务器的环境与你本地环境不同就不能直接copy过去了,最好的办法是下载一个服务器环境的SDKManager或者直接用Android Studio,然后对照你本地SDK里面的数据挨个下载,完了再copy到服务器。
247 |
248 |
249 |
250 |
251 |
252 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | //获取时间戳
3 | def getDate() {
4 | def date = new Date()
5 | def formattedDate = date.format('yyyyMMddHHmm')
6 | return formattedDate
7 | }
8 |
9 | def verCode = 14
10 | android {
11 | compileSdkVersion 22
12 | buildToolsVersion "23.0.3"
13 |
14 | signingConfigs {
15 | signingConfig {
16 | keyAlias 'xxx'
17 | keyPassword 'xxx'
18 | storeFile file('xxx')
19 | storePassword 'xxx'
20 | }
21 | }
22 |
23 | defaultConfig {
24 | applicationId "com.henanjianye.soon.communityo2o"
25 | minSdkVersion 14
26 | targetSdkVersion 22
27 | multiDexEnabled true
28 | versionCode verCode
29 | versionName APP_VERSION
30 | resValue("string", 'app_version', APP_VERSION)
31 | buildConfigField "boolean", "LEO_DEBUG", "true"
32 | buildConfigField 'String', 'API_SERVER_URL', RELEASE_API_SERVER_URL
33 | buildConfigField 'String', 'API_SERVER_URL_MALL', RELEASE_API_SERVER_URL_MALL
34 | generatedDensities = []
35 | signingConfig signingConfigs.signingConfig
36 | }
37 |
38 | compileOptions {
39 | sourceCompatibility JavaVersion.VERSION_1_7
40 | targetCompatibility JavaVersion.VERSION_1_7
41 | }
42 | lintOptions {
43 | abortOnError false
44 | }
45 | aaptOptions {
46 | additionalParameters "--no-version-vectors"
47 | }
48 | buildTypes {
49 | release {
50 | buildConfigField 'String', 'API_SERVER_URL', RELEASE_API_SERVER_URL
51 | buildConfigField 'String', 'API_SERVER_URL_MALL', RELEASE_API_SERVER_URL_MALL
52 | buildConfigField 'String', 'IM_SERVER_HOST', RELEASE_IM_SERVER_HOST
53 | buildConfigField 'int', 'IM_SERVER_PORT', RELEASE_IM_SERVER_PORT
54 | buildConfigField "boolean", "LEO_DEBUG", RELEASE_LEO_DEBUG
55 | minifyEnabled true
56 | zipAlignEnabled true
57 | shrinkResources true
58 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
59 | }
60 | ysc {
61 | buildConfigField 'String', 'API_SERVER_URL', YSC_API_SERVER_URL
62 | buildConfigField 'String', 'API_SERVER_URL_MALL', YSC_API_SERVER_URL_MALL
63 | buildConfigField 'String', 'IM_SERVER_HOST', YSC_IM_SERVER_HOST
64 | buildConfigField 'int', 'IM_SERVER_PORT', YSC_IM_SERVER_PORT
65 | buildConfigField "boolean", "LEO_DEBUG", YSC_LEO_DEBUG
66 | minifyEnabled true
67 | zipAlignEnabled true
68 | shrinkResources true
69 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
70 | }
71 | develop {
72 | buildConfigField 'String', 'API_SERVER_URL', DEVELOP_API_SERVER_URL
73 | buildConfigField 'String', 'API_SERVER_URL_MALL', DEVELOP_API_SERVER_URL_MALL
74 | buildConfigField 'String', 'IM_SERVER_HOST', DEVELOP_IM_SERVER_HOST
75 | buildConfigField 'int', 'IM_SERVER_PORT', DEVELOP_IM_SERVER_PORT
76 | buildConfigField "boolean", "LEO_DEBUG", DEVELOP_LEO_DEBUG
77 | minifyEnabled true
78 | zipAlignEnabled true
79 | shrinkResources true
80 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
81 | }
82 | inside_test {
83 | buildConfigField 'String', 'API_SERVER_URL', INSIDE_TEST_API_SERVER_URL
84 | buildConfigField 'String', 'API_SERVER_URL_MALL', INSIDE_TEST_API_SERVER_URL_MALL
85 | buildConfigField 'String', 'IM_SERVER_HOST', INSIDE_TEST_IM_SERVER_HOST
86 | buildConfigField 'int', 'IM_SERVER_PORT', INSIDE_TEST_IM_SERVER_PORT
87 | buildConfigField "boolean", "LEO_DEBUG", INSIDE_TEST_LEO_DEBUG
88 | minifyEnabled true
89 | zipAlignEnabled true
90 | shrinkResources true
91 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
92 | }
93 | debug {
94 | buildConfigField 'String', 'API_SERVER_URL', RELEASE_API_SERVER_URL
95 | buildConfigField 'String', 'API_SERVER_URL_MALL', RELEASE_API_SERVER_URL_MALL
96 | buildConfigField 'String', 'IM_SERVER_HOST', RELEASE_IM_SERVER_HOST
97 | buildConfigField 'int', 'IM_SERVER_PORT', RELEASE_IM_SERVER_PORT
98 | buildConfigField "boolean", "LEO_DEBUG", RELEASE_LEO_DEBUG
99 | }
100 | }
101 | dexOptions {
102 | javaMaxHeapSize "2g"
103 | }
104 |
105 | packagingOptions {
106 | exclude 'META-INF/DEPENDENCIES.txt'
107 | exclude 'META-INF/LICENSE.txt'
108 | exclude 'META-INF/NOTICE.txt'
109 | exclude 'META-INF/NOTICE'
110 | exclude 'META-INF/LICENSE'
111 | exclude 'META-INF/DEPENDENCIES'
112 | exclude 'META-INF/notice.txt'
113 | exclude 'META-INF/license.txt'
114 | exclude 'META-INF/dependencies.txt'
115 | exclude 'META-INF/LGPL2.1'
116 | }
117 |
118 | //渠道Flavors,我这里写了一些常用的
119 | productFlavors {
120 | commonsoon {
121 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "commonsoon"]
122 | }
123 | zhushou91 {
124 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "zhushou91"]
125 | }
126 | market360 {
127 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "market360"]
128 | }
129 | xiaomi {
130 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
131 | }
132 | wandoujia {
133 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
134 | }
135 | marketandroid {
136 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "marketandroid"]
137 | }
138 | yingyonghui {
139 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "yingyonghui"]
140 | }
141 | jifengmarket {
142 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "jifengmarket"]
143 | }
144 | mumayi {
145 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "mumayi"]
146 | }
147 | anzhimarket {
148 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "anzhimarket"]
149 | }
150 | yingyongbao {
151 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "yingyongbao"]
152 | }
153 | huaweimarket {
154 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "huaweimarket"]
155 | }
156 | }
157 | allprojects {
158 | repositories {
159 | mavenCentral()
160 | maven { url "https://jitpack.io" }
161 | }
162 | }
163 |
164 | //修改生成的apk名字
165 | applicationVariants.all { variant ->
166 | variant.outputs.each { output ->
167 | def newName
168 | def timeNow
169 | def oldFile = output.outputFile
170 | def outDirectory = oldFile.parent
171 |
172 | if ("true".equals(IS_JENKINS)) {
173 | timeNow = JENKINS_TIME
174 | outDirectory = 'G:/Tomcat/webapps/jenkins/apk'
175 | newName = 'yj-android-v' +
176 | APP_VERSION + '-' + variant.productFlavors[0].name + timeNow + '-' + variant.buildType.name + '.apk'
177 | } else {
178 | timeNow = getDate()
179 | if (variant.buildType.name.equals('debug')) {
180 | newName = "yj-android-v${APP_VERSION}-debug.apk"
181 | } else {
182 | newName = 'yj-android-v' +
183 | APP_VERSION + '-' + variant.productFlavors[0].name + timeNow + '-' + variant.buildType.name + '.apk'
184 | }
185 | }
186 |
187 | output.outputFile = new File(outDirectory, newName)
188 |
189 | }
190 | }
191 | }
192 |
193 | dependencies {
194 | compile fileTree(include: ['*.jar'], dir: 'libs')
195 |
196 | }
197 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Wed Aug 10 19:25:54 CST 2016
16 | android.useDeprecatedNdk=true
17 |
18 | #release config
19 | RELEASE_API_SERVER_URL="xxx"
20 | RELEASE_API_SERVER_URL_MALL="xxx"
21 | RELEASE_IM_SERVER_HOST="xxx"
22 | RELEASE_IM_SERVER_PORT=5222
23 | RELEASE_LEO_DEBUG=false
24 |
25 | #ysc config
26 | YSC_API_SERVER_URL="xxx"
27 | YSC_API_SERVER_URL_MALL="xxx"
28 | YSC_IM_SERVER_HOST="182.92.10.56"
29 | YSC_IM_SERVER_PORT=5222
30 | YSC_LEO_DEBUG=true
31 |
32 | #develop config
33 | DEVELOP_API_SERVER_URL="xxx"
34 | DEVELOP_API_SERVER_URL_MALL="xxx"
35 | DEVELOP_IM_SERVER_HOST="xxx"
36 | DEVELOP_IM_SERVER_PORT=5422
37 | DEVELOP_LEO_DEBUG=true
38 |
39 | #inside_test config
40 | INSIDE_TEST_API_SERVER_URL="xxx"
41 | INSIDE_TEST_API_SERVER_URL_MALL="xxx"
42 | INSIDE_TEST_IM_SERVER_HOST="xxx"
43 | INSIDE_TEST_IM_SERVER_PORT=5222
44 | INSIDE_TEST_LEO_DEBUG=true
45 |
46 | APP_VERSION=2.4.0
47 |
48 | IS_JENKINS=false
49 | JENKINS_TIME=''
--------------------------------------------------------------------------------
/image/image_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_1.png
--------------------------------------------------------------------------------
/image/image_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_10.png
--------------------------------------------------------------------------------
/image/image_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_11.png
--------------------------------------------------------------------------------
/image/image_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_12.png
--------------------------------------------------------------------------------
/image/image_13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_13.png
--------------------------------------------------------------------------------
/image/image_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_14.png
--------------------------------------------------------------------------------
/image/image_15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_15.png
--------------------------------------------------------------------------------
/image/image_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_16.png
--------------------------------------------------------------------------------
/image/image_17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_17.png
--------------------------------------------------------------------------------
/image/image_18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_18.png
--------------------------------------------------------------------------------
/image/image_19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_19.png
--------------------------------------------------------------------------------
/image/image_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_2.png
--------------------------------------------------------------------------------
/image/image_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_20.png
--------------------------------------------------------------------------------
/image/image_21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_21.png
--------------------------------------------------------------------------------
/image/image_22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_22.png
--------------------------------------------------------------------------------
/image/image_23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_23.png
--------------------------------------------------------------------------------
/image/image_24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_24.png
--------------------------------------------------------------------------------
/image/image_25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_25.png
--------------------------------------------------------------------------------
/image/image_26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_26.png
--------------------------------------------------------------------------------
/image/image_27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_27.png
--------------------------------------------------------------------------------
/image/image_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_28.png
--------------------------------------------------------------------------------
/image/image_29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_29.png
--------------------------------------------------------------------------------
/image/image_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_3.png
--------------------------------------------------------------------------------
/image/image_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_4.png
--------------------------------------------------------------------------------
/image/image_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_5.png
--------------------------------------------------------------------------------
/image/image_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_6.png
--------------------------------------------------------------------------------
/image/image_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_7.png
--------------------------------------------------------------------------------
/image/image_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_8.png
--------------------------------------------------------------------------------
/image/image_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/image/image_9.png
--------------------------------------------------------------------------------
/plugins.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mabeijianxi/android-automation/cefcfb7f9ece3d8ec71e44c338a6a65f78084996/plugins.zip
--------------------------------------------------------------------------------
/upload.py:
--------------------------------------------------------------------------------
1 | #coding: utf-8
2 | import os
3 | import re
4 | import requests
5 | import sys
6 |
7 | if len(sys.argv) == 2:
8 | mainpath = sys.argv[-1]
9 | else:
10 | exit()
11 |
12 | temppath = r'G:\mydownload\GETUI_ANDROID_SDK\GETUI_ANDROID_SDK\Demo\PushDemo\yijia\temp.apk'
13 |
14 | cmd = 'curl -F "file=@{path}" -F "uKey=xxx" -F "_api_key=xxx" http://www.pgyer.com/apiv1/app/upload'
15 | content = os.popen(cmd.format(path=mainpath)).read()
16 | print(content)
17 |
18 | match = re.search('"appKey":"(\w+)"', content)
19 |
20 | if match:
21 | appkey = match.group(1)
22 |
23 | content = os.popen(cmd.format(path=temppath)).read()
24 |
25 | url = 'http://static.pgyer.com/' + appkey
26 | html = requests.get(url).text
27 |
28 | match = re.search('http://static.pgyer.com/app/qrcodeHistory/\w+', html)
29 | if match:
30 | print('appKey#{soonAppkey}#appKeysoon#{soon}#soon'.format(soonAppkey=appkey,soon=match.group()))
31 | else:
32 | print('no qrcode')
33 |
--------------------------------------------------------------------------------