使用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’
}

“`
>在默认的基础上创建

“`
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         : “493935c58323ac450a011c352a9ade93”,
                            UMENG_APPKEY        : “583f89c4f29d984ce2000913”,
                            UMENG_MESSAGE_SECRET: “4a9fc81a6524eecfe33fac40e3a08b9f”]
}
“`
对应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>
“`
![项目目录](http://upload-images.jianshu.io/upload_images/3355043-5a93151f5c148991.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

如果需要替换java文件,同样需要在对应的文件夹下面创建同名的java文件,这时工程会报错,告诉你出现了同名文件,需要把main目录下面的java文件删除掉。

![报错](http://upload-images.jianshu.io/upload_images/3355043-b1557a035314dfa9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![删除后不报错](http://upload-images.jianshu.io/upload_images/3355043-acdf4d66503e30d4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

>打包配置(非必要)

先来个默认的
“`
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包

![签名打包](http://upload-images.jianshu.io/upload_images/3355043-6b5885399ef089b5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

我们看到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         : “493935c58323ac450a011c352a9ade93”,
                                    UMENG_APPKEY        : “583f89c4f29d984ce2000913”,
                                    UMENG_MESSAGE_SECRET: “4a9fc81a6524eecfe33fac40e3a08b9f”,
                                    PACKAGE_NAME        : “com.imyuu.saas.caihonggu”]
        }
        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’
}
“`

IT文库 » 使用Gradle动态配置资源
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址