如何使用Android Gradle替换字符串资源

时间:2013-06-24 12:26:53

标签: android gradle android-studio

我在Android Studio中使用gradle创建了一个新的应用程序,现在我需要在资源中制作大约10个具有不同包名和值的版本。我在示例中制作了自定义flavor,并希望使用自定义值替换此自定义flavor中的一些字符串。我找到了这样的例子:

filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: ['version': '2.2'])

但我不知道该把它放在哪里。据我所知,我需要把它放到单独的任务中,但如何让IDE调用这个任务?

此外,我需要在Java类和Content Provider的auth中替换一些变量,也许我需要通过将文件复制到flavor1文件夹并让gradle合并它来实现这一点,但是它似乎是错误的解决方案来存储许多文件的副本在一行中的差异...也许我需要为这一切使用其他解决方案?

这是build.gradle:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4.2'
    }
}
apply plugin: 'android'

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    compile project(':JazzyListView')
    compile project(':ABS')
    compile project(':Volley')
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        versionCode 5
        versionName "3.0"
        minSdkVersion 8
        targetSdkVersion 17
    }

    sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java']
            res.srcDirs = ['src/main/res']
        }
    }

    productFlavors {
        flavor1 {
            packageName "com.example.flavor1"               
        }

        flavor2 {
            packageName "com.example.flavor2"
        }

    }

}

4 个答案:

答案 0 :(得分:18)

我有类似的问题。我想将Jenkins内部版本号添加到从strings.xml合并的字符串中。这是Android Gradle插件0.12。+。

的解决方案
// Insert the build number into strings.xml
android.applicationVariants.all{ variant ->
    variant.mergeResources.doLast{
        ext.env = System.getenv()
        def buildNumber = env.BUILD_NUMBER
        if (buildNumber != null) {
            File valuesFile = file("${buildDir}/intermediates/res/${variant.dirName}/values/values.xml")
            println("Replacing revision number in " + valuesFile)
            println("Build number = " + buildNumber)
            String content = valuesFile.getText('UTF-8')
            content = content.replaceAll(/devBuild/, buildNumber)
            valuesFile.write(content, 'UTF-8')
        }
    }
}

您可能希望根据要执行的操作挂钩到不同的Gradle任务。看一下Android构建中的任务来解决这个问题。

http://tools.android.com/tech-docs/new-build-system/user-guide

更新:在某些时候,Android Gradle插件改变了从每个所有的应用程序变体关键字的方式。我的答案已更新以反映更改,但如果此代码未向控制台打印任何内容,请尝试切换到每个

答案 1 :(得分:4)

我试图获得与Maven资源过滤类似的功能。 这就是我提出的。我的解决方案可以使用一些更改来更健壮(即从属性文件中提取等)。

我的例子展示了如何替换单个值,这就是我所需要的。变量遵循${some.property}约定。此解决方案还适用于具有自己的资源文件的产品风格。

import org.apache.tools.ant.filters.*
...
android.applicationVariants.all{ variant ->
    // Perform resource filtering
    variant.mergeResources.doLast {
        filterResources(variant)
    }
}

def filterResources(buildVariant) {

    //Setup temp directory to filter the resources
    File resFiltered = file("${buildDir}/res/all/filtered/${buildVariant.dirName}")
    if(resFiltered.exists()){
        resFiltered.delete()
    }

    //Copy and filter the resources.
    copy {
        from(buildVariant.processResources.resDir) {
            include '**/*.xml'

            //Could be improved upon to pull from a properties file, etc.
            ant.properties['app.version'] = project.version

            filter(ExpandProperties, project: ant.project)

        }
        from(buildVariant.processResources.resDir) {
            exclude '**/*.xml'
        }

        into resFiltered

    }

    //Delete all the original resource files
    file(buildVariant.processResources.resDir).deleteDir()
    //Replace with the filtered ones.
    resFiltered.renameTo(file(buildVariant.processResources.resDir))
    //Delete the original 'filtered' directory
    file( "${buildDir}/res/all/filtered").deleteDir()
}

strings.xml中的示例

 ...
 <string name="app_version">${app.version}</string>
 ...

答案 2 :(得分:2)

在“src”文件夹中,创建与“main”文件夹具有相同层次结构的“flavor1”和“flavor2”文件夹。如果你的main / res / values中有strings.xml,你也可以在flavor1 / res / values中执行,并在那里有替换值。它可能会在IDE中显示错误,但仍应构建并运行。

答案 3 :(得分:1)

这些链接可能会有所帮助:

我的过滤器定义使用正则表达式来替换某些内容:

from('res/') {
    include '**/*.xml'
    filter {
        line -> line.replaceAll(/YOUR_REGEX_TO_REPLACE_SOMETHING/, 'REPLACED_RESULT_EXPRESSION')
    }
}
into 'build/path/to/your/filtered/resources/'