Как заменить строки ресурсов на Android Gradle

Я создал новое приложение с gradle в Android Studio, и теперь мне нужно сделать около 10 версий с разными именами пакетов и значениями в ресурсах. Я сделал специальные вкусы, как в примере, и хочу заменить некоторые строки в этих пользовательских вкусах на пользовательские значения. Я нашел такой пример:

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

Но я не знаю, куда его поместить. Как я понимаю, мне нужно поставить его в отдельную задачу, но как сделать эту задачу вызванной IDE?

Также мне нужно заменить несколько переменных внутри классов Java и Autodesk Content Provider, возможно, мне нужно сделать это, скопировав файлы в папку 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"
        }

    }

}

Ответы

Ответ 1

У меня была аналогичная проблема. Я хотел добавить номер сборки 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

UPDATE. В какой-то момент плагин Android Gradle изменил способ итерации по ключевому слову вариантов приложений от каждого к каждому. Мой ответ был обновлен, чтобы отразить изменения, но попробуйте переключиться на каждый, если этот код ничего не печатает на консоли.

Ответ 2

Я пытался получить аналогичную функциональность, такую ​​как фильтрация ресурсов 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>
 ...

Ответ 3

В папке "src" создайте папки "flavor1" и "flavor2" с той же иерархией, что и ваша "основная" папка. Если у вас есть strings.xml в ваших основных /res/values, вы можете сделать это в flavor1/res/values, а также иметь там значения замены. Он может показывать ошибки в среде IDE, но он все равно должен строиться и запускаться.

Ответ 4

Эти ссылки могут быть полезны:

И мое определение фильтра с использованием регулярного выражения для замены:

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