buildConfigField метод не виден в отдельном gradle файле

344
19 июля 2017, 22:32

Дано:

  1. Несколько flavors (en, es etc)
  2. Файл myData.properties для каждого flavor в папке project/config/{FLAVOR_NAME}
  3. Самостоятельно созданный gradle файл для заполнения полей в BuildConfig.java из данных файла из п2

Цель:

Вызвать мой метод в процессе сборки конкретного выбранного flavor и заполнить поля в BuildConfig.java

Проблема:

Я могу передать в мой метод имя flavor-а в виде строки и таким образом в методе получить путь до файла с данными, но buildConfigField метод в этом случае не виден.

Также я могу передать ApplicationVariant variant в мой метод и вызывать variant.buildConfigField в моём методе. Но в этом случае я не могу получить переменную ApplicationVariant variant в productFlavors блоке build.gradle(module app). Я могу получить её лишь за пределами этой секции путём пробега по всем вообще вариантам сборки applicationVariants.all { variant -> fillArrays(variant)}, но в этом случае я обязательно должен или поместить файлы с данными для всех вариантов или не кидать ошибку при отсутствии оного.

TL/DR:

Как вызвать buildConfigField метод в собственном gradle файле или как получить ApplicationVariant variant внутри блока productFlavors

marketSkusCreator.gradle

ext {
    fillArrays = { variant ->
        def pathToFileWithData = "config/" + variant.productFlavors[0].name + "/marketSkus.properties"
        if (rootProject.file(pathToFileWithData).exists()) {
            def marketSkusPropertiesFile = rootProject.file(pathToFileWithData);
            def properties = new Properties()
            properties.load(new FileInputStream(marketSkusPropertiesFile))
            //buildConfigField - method not found, so I cant pass only flavor name as string to fillArrays method
            //buildConfigField('String[]', 'OLD_SKUS', properties.get("marketSkusOld"))
            variant.buildConfigField('String[]', 'OLD_SKUS', properties.get("marketSkusOld"))
            variant.buildConfigField('String[]', 'VER_2_SKUS', properties.get("marketSkusVer2"))
            variant.buildConfigField('String[]', 'INAPP_SKUS', properties.get("marketSkusInapp"))
        } else {
            logger.lifecycle('pathToFileWithData: {}', pathToFileWithData)
            throw new GradleException("You need to have marketSkus.properties file in root of project with " +
                    "marketSkusOld," +
                    "marketSkusVer2," +
                    " variables to build project")
        }
    }
}

build.gradle(module app) (с сокращениями)

import com.android.build.gradle.api.ApplicationVariant
apply plugin: 'com.android.application'
apply from: '../marketSkusCreator.gradle'
android {
    compileSdkVersion 25
    buildToolsVersion '25.0.3'
    productFlavors {
        es {
            fillArrays(curVariant) //how to get it - {curVariant} (type: ApplicationVariant)
        }
        en {
            fillArrays(curVariant) //how to get it - {curVariant} (type: ApplicationVariant)
        }
    }
    //this works, but I do not want to call method for each flavor during each build
    //applicationVariants.all {ApplicationVariant variant ->
    //    fillArrays(variant)
    //}
}

Этот же вопрос на англо-саксонском: buildConfigField method not found in separate gradle file

Answer 1

Вот такой файл marketSkusCreator.gradle для вас должен подойти:

import java.util.regex.Matcher
import java.util.regex.Pattern
def getCurrentBuildType() {
    Gradle gradle = getGradle()
    String  tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
    if (tskReqStr.contains("Release")) {
        println "getCurrentBuildType release"
        return "release"
    }
    else if (tskReqStr.contains("Debug")) {
        println "getCurrentBuildType debug"
        return "debug"
    }
    return "";
}
def getCurrentFlavor() {
    Gradle gradle = getGradle()
    String  tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
    Pattern pattern;
    if( tskReqStr.contains( "assemble" ) )
        pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
    else
        pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
    Matcher matcher = pattern.matcher( tskReqStr )
    if( matcher.find() )
        return matcher.group(1).toLowerCase()
    else
    {
        return "";
    }
}
ext {
    fillArrays = { variant ->
        def pathToFileWithData = "config/" + variant.productFlavors[0].name + "/marketSkus.properties"
        def buildTypeName = variant.buildType.name
        def flavorName = variant.productFlavors[0].name;
        if (getCurrentFlavor() == flavorName && buildTypeName == getCurrentBuildType())
        {
            project.logger.lifecycle(pathToFileWithData)
            if (rootProject.file(pathToFileWithData).exists()) {
                def marketSkusPropertiesFile = rootProject.file(pathToFileWithData);
                def properties = new Properties()
                properties.load(new FileInputStream(marketSkusPropertiesFile))
                //buildConfigField - method not found, so I cant pass only flavor name as string to fillArrays method
                //buildConfigField('String[]', 'OLD_SKUS', properties.get("marketSkusOld"))
                variant.buildConfigField('String[]', 'OLD_SKUS', properties.get("marketSkusOld"))
                variant.buildConfigField('String[]', 'VER_2_SKUS', properties.get("marketSkusVer2"))
                variant.buildConfigField('String[]', 'INAPP_SKUS', properties.get("marketSkusInapp"))
            } else {
                logger.lifecycle('pathToFileWithData: {}', pathToFileWithData)
                throw new GradleException("You need to have marketSkus.properties file in root of project with " +
                        "marketSkusOld," +
                        "marketSkusVer2," +
                        " variables to build project")
            }
        }
    }
}

А уже в build.gradle(module app) вызываете:

applicationVariants.all { variant ->
            fillArrays(variant)
        }

P.S. функция getCurrentFlavor() взята отсюда

READ ALSO
Вывести числа на нечетных позициях

Вывести числа на нечетных позициях

Не могу разобраться с итераторами, здесь он выводит просто подряд числа, как сделать так, чтобы выводились числа, которые стоят на нечетной...

356
Работа с файлом на удаленке

Работа с файлом на удаленке

Selenium + TestNG + Winium(Java)

296
Ошибка при попытке Run или Debug в Android Studio

Ошибка при попытке Run или Debug в Android Studio

Здраствуйте, у меня никак не может исчезнуть одна ошибка, никак не могу найти ответ на свой вопросУ меня возникает вот такая ошибка при попытке...

361