-
Notifications
You must be signed in to change notification settings - Fork 1
/
note.txt
318 lines (255 loc) · 9.97 KB
/
note.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
Gradle多渠道打包
http://stormzhang.com/devtools/2015/01/15/android-studio-tutorial6/
由于国内Android市场众多渠道,为了统计每个渠道的下载及其它数据统计,就需要我们针对每个渠道单独打包,如果让你打几十个市场的包岂不烦死了,不过有了Gradle,这再也不是事了。
友盟多渠道打包
废话不多说,以友盟统计为例,在AndroidManifest.xml里面会有这么一段:
<meta-data
android:name="UMENG_CHANNEL"
android:value="Channel_ID" />
里面的Channel_ID就是渠道标示。我们的目标就是在编译的时候这个值能够自动变化。
第一步 在AndroidManifest.xml里配置PlaceHolder
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
第二步 在build.gradle设置productFlavors
android {
productFlavors {
xiaomi {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
}
_360 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "_360"]
}
baidu {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
}
wandoujia {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
}
}
或者批量修改
android {
productFlavors {
xiaomi {}
_360 {}
baidu {}
wandoujia {}
}
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
很简单清晰有没有?直接执行 ./gradlew assembleRelease , 然后就可以静静的喝杯咖啡等待打包完成吧。
assemble结合Build Variants来创建task
上一篇博客介绍了 assemble 这个命令,会结合 Build Type 创建自己的task,如:
./gradlew assembleDebug
./gradlew assembleRelease
除此之外 assemble 还能和 Product Flavor 结合创建新的任务,其实 assemble 是和 Build Variants 一起结合使用的,而 Build Variants = Build Type + Product Flavor , 举个例子大家就明白了:
如果我们想打包wandoujia渠道的release版本,执行如下命令就好了:
./gradlew assembleWandoujiaRelease
如果我们只打wandoujia渠道版本,则:
./gradlew assembleWandoujia
此命令会生成wandoujia渠道的Release和Debug版本
同理我想打全部Release版本:
./gradlew assembleRelease
这条命令会把Product Flavor下的所有渠道的Release版本都打出来。
总之,assemble 命令创建task有如下用法:
**assemble**: 允许直接构建一个Variant版本,例如assembleFlavor1Debug。
**assemble**: 允许构建指定Build Type的所有APK,例如assembleDebug将会构建Flavor1Debug和Flavor2Debug两个Variant版本。
**assemble**: 允许构建指定flavor的所有APK,例如assembleFlavor1将会构建Flavor1Debug和Flavor1Release两个Variant版本。
完整的gradle脚本
最后福利大放送,来一份我在项目中使用的完整的gradle文件配置:
apply plugin: 'com.android.application'
def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
android {
compileSdkVersion 21
buildToolsVersion '21.1.2'
defaultConfig {
applicationId "com.boohee.*"
minSdkVersion 14
targetSdkVersion 21
versionCode 1
versionName "1.0"
// ndk {
// moduleName "tp_file"
// //stl "stlport_shared" //对应APP_STL
// ldLibs "log", "z", "m" //链接时使用到的库,对应LOCAL_LDLIBS
// //cFlags 编译gcc的flag,对应LOCAL_CFLAGS
// }
// dex突破65535的限制
multiDexEnabled true
// 默认是umeng的渠道
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "umeng"]
}
lintOptions {
abortOnError false
}
signingConfigs {
debug {
// No debug config
}
release {
storeFile file("../yourapp.keystore")
storePassword "your password"
keyAlias "your alias"
keyPassword "your password"
}
}
buildTypes {
debug {
// 显示Log
buildConfigField "boolean", "LOG_DEBUG", "true"
versionNameSuffix "-debug"
minifyEnabled false
zipAlignEnabled false
shrinkResources false
signingConfig signingConfigs.debug
}
release {
// 不显示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
minifyEnabled true
zipAlignEnabled true
// 移除无用的resource文件
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
// 输出apk名称为boohee_v1.0_2015-01-15_wandoujia.apk
def fileName = "boohee_v${defaultConfig.versionName}_${releaseTime()}_${variant.productFlavors[0].name}.apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
}
// 友盟多渠道打包
productFlavors {
wandoujia {}
_360 {}
baidu {}
xiaomi {}
tencent {}
taobao {}
...
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:support-v4:21.0.3'
implementation 'com.jakewharton:butterknife:6.0.0'
...
}
//自动化打包
import com.android.build.gradle.internal.dsl.ProductFlavor
import com.android.builder.core.AndroidBuilder
import groovy.json.JsonSlurper
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "esg.sykes.autopackage.app"
minSdkVersion 8
targetSdkVersion 21
versionCode 1
versionName "1.0"
// buildConfigField("String", "testString", "\"this is test field\"")
// buildConfigField("boolean", "testBoolean", "true")
// buildConfigField("int", "testInt", "146")
}
signingConfigs {
release {
storeFile file('store.jks')
storePassword 'sunjianan22'
keyAlias 'jonesun'
keyPassword 'sunjianan22'
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
String productFlavorsJson = new File(getProjectDir().getPath() + File.separator + "products.json").text;
// println("productFlavorsJson: " + productFlavorsJson)
def products = new JsonSlurper().parseText(productFlavorsJson).products
// println("products: " + products)
products.collect { product ->
product.productFlavors.collect { flavor ->
ProductFlavor productFlavor = android.productFlavors.create(product.id + "_" + flavor.channel.id)
productFlavor.setApplicationId(flavor.applicationId)
// if(flavor.minSdkVersion == 0){
// flavor.minSdkVersion = 8;
// productFlavor.setMinSdkVersion(flavor.minSdkVersion)
// }
// if(flavor.targetSdkVersion == 0){
// flavor.targetSdkVersion = 21
// productFlavor.setTargetSdkVersion(flavor.targetSdkVersion)
// }
productFlavor.versionName = flavor.versionName
productFlavor.versionCode = flavor.versionCode
productFlavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: flavor.channel.umeng_value]
def sourceSet = sourceSets.getByName(productFlavor.getName())
sourceSet.java.srcDirs = ['src/' + product.id + '/java']
sourceSet.res.srcDirs = ['src/' + product.id + '/res']
sourceSet.assets.srcDirs = ['src/' + product.id + '/assets']
flavor.buildConfigFields.collect{ buildConfigField ->
String value = buildConfigField.value;
if(buildConfigField.type == "String"){
value = '"' + value + '"';
}
productFlavor.addBuildConfigField(AndroidBuilder.createClassField(buildConfigField.type, buildConfigField.name, value))
}
println("productFlavor: " + productFlavor)
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:22.2.0'
implementation 'com.google.code.gson:gson:2.3'
}
D:\>keytool -list -v -keystore store.jks
输入密钥库口令:
密钥库类型: JKS
密钥库提供方: SUN
您的密钥库包含 1 个条目
别名: jonesun
创建日期: 2014-5-5
条目类型: PrivateKeyEntry
证书链长度: 1
证书[1]:
所有者: CN=jone sun, OU=Jone, L=suzhou, ST=jiangsu, C=ZH
发布者: CN=jone sun, OU=Jone, L=suzhou, ST=jiangsu, C=ZH
序列号: 5796d294
有效期开始日期: Mon May 05 12:53:42 CST 2014, 截止日期: Fri Apr 29 12:53:42 CST
2039
证书指纹:
MD5: 87:39:D7:B3:3D:06:D7:8A:EA:E5:10:D2:24:B8:E9:30
SHA1: 8C:0D:D9:A6:8A:19:14:37:4A:29:82:74:5E:E3:17:9B:88:62:5D:30
SHA256: C6:80:1F:F1:84:C2:B2:49:80:C5:34:F2:8F:2F:2C:0A:F5:54:FE:58:C7:
8E:76:4A:97:16:C3:7A:A7:A2:0C:E4
签名算法名称: SHA256withRSA
版本: 3
扩展:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 8D 0F 1B C6 BD 0C 56 C1 CE 27 06 52 D4 FD E3 25 ......V..'.R...%
0010: 93 99 11 16 ....
]
]
*******************************************
*******************************************