使用Gradle动态配置资源
使用Gradle动态配置资源
关键词:Gradle 多渠道打包 动态更换资源
Eclipse中可以使用Ant动态替换文件中的字符串,或者替换文件实现动态更换项目资源,实现快速打包。
例如:可以实现多渠道打包,debug版与release版访问不同服务器可以动态替换,多个app差异只是 App名字 , App图标 或者 App访问的服务器不同,这些使用gradle可以更方便的做到,而且gradle不是替换资源,而是配置资源。
- 先来一个默认的
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "net.ljt.gradledemo"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.1.0'
testCompile 'junit:junit:4.12'
}
在默认的基础上添加productFlavors
android {
...
productFlavors{
}
...
}
在productFlavors里面创建不同包的标签
productFlavors {
xiaomi {}
baidu {}
huawei {}
yingyongbao {}
_360{}
}
当然也可以创建其他非应用商店的标签,例如你要打包多个不同名字的apk,那么就用不同的名字作标签
productFlavors {
xiaomi {}
baidu {}
huawei {}
yingyongbao {}
_360{}
gradle{}
gradledemo{}
}
在标签中指定需要替换的资源
- 在这里你可以指定你的包名,版本号,版本ID,签名文件等内容
android {
...
defaultConfig {
applicationId "net.ljt.gradledemo"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
signingConfigs {
xiaomi {
keyAlias 'xiaomi'
keyPassword 'xiaomi123'
storeFile file('xiaomi.keystore')
storePassword 'xiaomi123'
}
baidu {
keyAlias 'baidu'
keyPassword 'baidu123'
storeFile file('baidu.keystore')
storePassword 'baidu123'
}
}
productFlavors {
xiaomi {
applicationId "net.ljt.gradle.xiaomi"
minSdkVersion 15
targetSdkVersion 25
versionCode 3
versionName "1.2"
signingConfig signingConfigs.xiaomi
}
baidu {
applicationId "net.ljt.gradle.baidu"
minSdkVersion 15
targetSdkVersion 24
versionCode 2
versionName "1.1"
signingConfig signingConfigs.baidu
}
huawei {}
yingyongbao {}
_360{}
gradle{}
gradledemo{}
}
...
}
如果你的flavor里面只是替换非常简单的字符串,例如渠道号,就可以简略的这样写
productFlavors {
xiaomi {}
baidu {}
huawei {}
yingyongbao {}
_360{}
gradle{}
gradledemo{}
}
//使用循环遍历所有flavor
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
使用manifestPlaceholders指定需要替换的AndroidManifest.xml文件中的资源
xiaomi {
...
manifestPlaceholders = [AMAP_APIKEY : "4598462156234arh456bsehsd5",
UMENG_APPKEY : "95aerh5h4sr4s65h65f4gha",
UMENG_MESSAGE_SECRET: "54FGB4A5B4a45eth45a5FA5s5g45dn"]
}
对应AndroidManifest.xml中使用下面字段代替
${AMAP_APIKEY}
${UMENG_APPKEY}
${UMENG_MESSAGE_SECRET}
替换资源
如果需要替换图片,string.xml文件中的资源,需要在src目录下main文件夹同级目录创建对应标签的文件夹,并且在文件夹下创建对应需要替换内容的文件的目录,对于图片,放置一个同名图片即可,对于string.xml文件,只需要在里面指定需要替换的部分即可
- main里面的string.xml文件
<resources>
<string name="app_name">GradleDemo</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
</resources>
- _360里面的配置string.xml
<resources>
<string name="app_name">_360</string>
</resources>
项目目录
如果需要替换java文件,同样需要在对应的文件夹下面创建同名的java文件,这时工程会报错,告诉你出现了同名文件,需要把main目录下面的java文件删除掉。
报错 删除后不报错打包配置(非必要)
先来个默认的
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
再来一个自定义打包的
buildTypes {
release {
// 不显示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
minifyEnabled true
shrinkResources true //移除无用资源
debuggable false
zipAlignEnabled true //zipalign优化
signingConfig signingConfigs.hxtx
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// 自定义输出配置
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
//在这里可以自定义打包后的文件名
def fileName = "${variant.flavorName}_${variant.versionName}_${releaseTime()}.apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
//过滤掉unaligned的包
variant.assemble.doLast {
variant.outputs.each { output ->
File unaligned = output.packageApplication.outputFile;
File aligned = output.outputFile
if (!unaligned.getName().equalsIgnoreCase(aligned.getName())) {
unaligned.delete()
}
}
}
}
}
}
这里用到了一个releaseTime()函数,需要在gradle文件中定义这个函数
def releaseTime() {
return new Date().format("yyyy-MM-dd-HH-mm-ss", TimeZone.getTimeZone("UTC"))
}
打包
使用Android Studio打包签名的apk包
签名打包我们看到Flavors里面是我们配置过的一些渠道名,这里你可以单选也可以多选,每一个Flavors都对应一个apk包
最后祭出完整版的Gradle文件
apply plugin: 'com.android.application'
def releaseTime() {
return new Date().format("yyyy-MM-dd-HH-mm-ss", TimeZone.getTimeZone("UTC"))
}
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
signingConfigs {
xiaomi {
keyAlias 'xiaomi'
keyPassword 'xiaomi123'
storeFile file('xiaomi.keystore')
storePassword 'xiaomi123'
}
baidu {
keyAlias 'baidu'
keyPassword 'baidu123'
storeFile file('baidu.keystore')
storePassword 'baidu123'
}
}
defaultConfig {
applicationId "net.ljt.gradledemo"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// 不显示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
minifyEnabled true
shrinkResources true //移除无用资源
debuggable false
zipAlignEnabled true //zipalign优化
signingConfig signingConfigs.hxtx
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// 自定义输出配置
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = "${variant.flavorName}_${variant.versionName}_${releaseTime()}.apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
//过滤掉unaligned的包
variant.assemble.doLast {
variant.outputs.each { output ->
File unaligned = output.packageApplication.outputFile;
File aligned = output.outputFile
if (!unaligned.getName().equalsIgnoreCase(aligned.getName())) {
unaligned.delete()
}
}
}
}
}
}
productFlavors {
xiaomi {
applicationId "net.ljt.gradle.xiaomi"
minSdkVersion 15
targetSdkVersion 25
versionCode 3
versionName "1.2"
signingConfig signingConfigs.xiaomi
manifestPlaceholders = [AMAP_APIKEY : "564561543612315AERG5S4561B",
UMENG_APPKEY : "54asg1s5bvga6g6AfbaG5",
UMENG_MESSAGE_SECRET: "4af5g4aw5fgae565fge44a56ear",
PACKAGE_NAME : "com.xxxx.xxxx"]
}
baidu {
applicationId "net.ljt.gradle.baidu"
minSdkVersion 15
targetSdkVersion 24
versionCode 2
versionName "1.1"
signingConfig signingConfigs.baidu
}
huawei {}
yingyongbao {}
_360{}
gradle{}
gradledemo{}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.1.0'
testCompile 'junit:junit:4.12'
}