Jak wygenerować buildConfigField z typem String

145

W moim Android Studioprojekcie są dwa build configurationz kilkoma buildConfigField:

    buildTypes {
    def SERVER_URL = "SERVER_URL"
    def APP_VERSION = "APP_VERSION"

    debug {
        buildConfigField "String", SERVER_URL, "http://dev.myserver.com"
        buildConfigField "String", APP_VERSION, "0.0.1"
    }

    release {
        buildConfigField "String", SERVER_URL, "https://myserver.com"
        buildConfigField "String", APP_VERSION, "0.0.1"

        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

Otrzymuję i błąd w następujący sposób:

/path/to/generated/BuildConfig.java
    Error:(14, 47) error: ';' expected
    Error:(15, 47) error: ';' expected

generowany BuildConfig.javajest następujący:

public final class BuildConfig {
    public static final boolean DEBUG = Boolean.parseBoolean("true");
    public static final String APPLICATION_ID = "com.mycuteoffice.mcoapp";
    public static final String BUILD_TYPE = "debug";
    public static final String FLAVOR = "";
    public static final int VERSION_CODE = 1;
    public static final String VERSION_NAME = "1.0";
    // Fields from build type: debug
    public static final String APP_VERSION = 0.0.1;
    public static final String SERVER_URL = http://dev.mycuteoffice.com;
}

Myślę, że APP_VERSIONi SERVER_URLnie są generowane poprawnie, ponieważ są typu String, nie mają cudzysłowów.

Nie jestem pewien, dlaczego jest generowany w taki sposób. Daj mi znać, jak mogę rozwiązać ten problem.

Abdullah
źródło
Po prostu dodaj pojedyncze cudzysłowy wokół wartości z podwójnymi cudzysłowami: buildConfigField "String", APP_VERSION, ' "0.0.1" '(oczywiście bez spacji)
Pierre

Odpowiedzi:

254

Pola konfiguracji budowania typu ciągowego należy zadeklarować w następujący sposób:

buildConfigField "String", "SERVER_URL", "\"http://dev.myserver.com\""

nazwa pola w cudzysłowie, dodatkowo wartość pola w cudzysłowie.

Vladyslav Matviienko
źródło
1
Pytanie miało na celu użycie „SERVER_URL” jako zmiennej. Umieszczenie „SERVER_URL” w cudzysłowie powoduje, że wartość staje się literałem typu String. Dlatego odpowiedź @ madhead jest poprawniejsza (i ładniejsza).
Will Vanderhoef,
1
@WillVanderhoef, całkowicie się mylisz. Po prostu nie działa, jeśli nie umieścisz go SERVER_URLw cudzysłowie. Wiedziałbyś o tym, gdybyś spróbował sam przed komentarzem. Komunikat o błędzie toError:(32, 0) Could not find property 'SERVER_URL' on BuildType_...
Vladyslav Matviienko
Mój błąd. Użyłem odpowiedzi Simasa jako podstawy i po prostu ją skopiowałem. Nie chodziło mi o trzecie pole (nazwa zmiennej), ale o używanie podwójnych cudzysłowów do ucieczki wartości zmiennej: jeśli sama zmienna nie ma podwójnych cudzysłowów, możesz po prostu pojedyncze zewnętrzne cudzysłowy, aby pozbyć się odwrotnych ukośników. Zredagowałem obie odpowiedzi.
szalony
@VladMatvienko zdecydowanie działa, właściwie używam go tak, jak opisuję. def FIELD_NAME = "SERVER_URL"i buildConfigField "boolean", FIELD_NAME, "false"dobrze ze sobą współpracować. Jeśli brakuje definicji SERVER_URL, nastąpi awaria, prawdopodobnie to właśnie robisz źle.
Will Vanderhoef
2
@WillVanderhoef, tak, o tym zapomniałeś wspomnieć - używasz cudzysłowów podczas definicji. Twoje rozwiązanie ma 1 dodatkową linię i również używa cudzysłowów, dlatego nie jest tak dobre jak moje.
Vladyslav Matviienko
96

Dlaczego wszyscy tak szaleni unikają podwójnych cudzysłowów? Wygląda brzydko! To jest Groovy, chłopaki, możecie po prostu mieszać pojedyncze i podwójne cudzysłowy:

buildConfigField "String", 'SERVER_URL', '"http://dev.myserver.com"'
buildConfigField "String", 'APP_VERSION', '"0.0.1"'
szaleniec
źródło
5
To wciąż nie jest droga, nie powinniśmy musieć uciekać ani używać zagnieżdżonych cudzysłowów, ponieważ jest to String
Fabio
4
@Fabio Używanie zagnieżdżonych cudzysłowów pozwala na użycie wyrażeń, które można ocenić. Zobacz tę odpowiedź .
Albert Vila Calvo,
31

Jeśli przez „rozwiązywanie problemów” masz na myśli brak konieczności podwójnego cytowania literałów, nie znalazłem niczego, ponieważ wydaje się, że działa zgodnie z założeniami.

Eksperymentowałem z przeniesieniem literałów do „ gradle.properties ” jako obejściem, zamieniając potencjalnie wiele brzydkich wierszy w jeden brzydki wiersz.

Tak jak to:

buildTypes {
def SERVER_URL = "SERVER_URL"
def APP_VERSION = "APP_VERSION"

def CONFIG = { k -> "\"${project.properties.get(k)}\"" }

debug {
    buildConfigField "String", SERVER_URL, CONFIG("debug.server.url")
    buildConfigField "String", APP_VERSION, CONFIG("version")
}

release {
    buildConfigField "String", SERVER_URL, CONFIG("release.server.url")
    buildConfigField "String", APP_VERSION, CONFIG("version")

    minifyEnabled false
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

gradle.properties

version=0.1.1
...
debug.server.url=http://dev.myserver.com
...
release.server.url=http://myserver.com
...

Dalsze przemyślenia:


def CONFIG = { b,k -> "\"${project.properties.get(b+'.'+k)}\"" }
def CONFIG_DEBUG = { k -> CONFIG('debug',k) }
def CONFIG_RELEASE = { k -> CONFIG('release',k) }

def CONFIG = { b,k -> "\"${project.properties.get(b+'.'+k)}\"" }
def CONFIG_INT = { b,k -> "${project.properties.get(b+'.'+k)}" }
...
Primexx
źródło
Mam pole konfiguracji kompilacji i chcę uzyskać dostęp do tej zmiennej w myn def w tym samym gradle .. Jestem nowy w gradle plz helpp!
Adeel Turk
Dzięki za skrypt CONFIG! W drużynie nieznacznie poprawiliśmy to, aby wyrzucić wyjątek, jeśli var nie istnieje: CONFIG = { k -> if (project.properties.containsKey(k)) "\"${project.properties.get(k)}\"" else throw new RuntimeException("No such variable: " + k) }
demaksee
9

Ja też byłem zdezorientowany. Ale ma sens - „String” definiuje typ pola, podczas gdy wartość pola nie jest automatycznie cytowana, abyśmy mogli użyć tutaj wyrażeń:

buildConfigField "String", "TEST", "new Integer(10).toString()"

W przeciwnym razie nie byłoby to możliwe.

geiger
źródło
Jest to możliwe, jeśli używasz interpolacji ciągów, np .: buildConfigField "String", "TEST", "\" $ {10} \ "" W ten sposób możesz również użyć metod lub zmiennych w pliku kompilacji.
Szörényi Ádám
9

Uniknij cudzysłowów:

buildConfigField "String", 'SERVER_URL', "\"http://dev.myserver.com\""
buildConfigField "String", 'APP_VERSION', "\"0.0.1\""
Simas
źródło
5

Posługiwać się

 buildConfigField "String", "FILE_NAME", "\"{$fileName}\"" 

dla zmiennej. Odniesienie stąd

Audi
źródło
2

w aplikacji build.gradle

def buildTimeAndVersion = releaseTime() + "-" + getSvnVersion()    
buildTypes {
debug {
    signingConfig signingConfigs.config
    buildConfigField "String", 'BIULD_TIME', "\"${buildTimeAndVersion}\""
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
...
}

static def releaseTime() {
return new Date().format("yyyyMMdd", TimeZone.getDefault())
}

def getSvnVersion() {
def pro = ("svnversion -c " + getBuildDir().parent).execute()
pro.waitFor()
def version = pro.in.text
Pattern p = Pattern.compile("(\\d+\\:)?(\\d+)\\D?")
Matcher m = p.matcher(version)
if (m.find()) {
version = m.group(m.groupCount())
}
try {
return version
} catch (e) {
println e.getMessage()
}
return 0
}

następnie w BuildConfig

public final class BuildConfig {  
public static final boolean DEBUG = Boolean.parseBoolean("true");   
public static final String APPLICATION_ID = "xxx.xxxxxxxx.xxx";   
public static final String BUILD_TYPE = "debug";  
public static final String FLAVOR = "";  
public static final int VERSION_CODE = 53;  
public static final String VERSION_NAME = "5.4.4";  
// Fields from build type: debug  
public static final String BIULD_TIME = "20181030-2595";  
}
yitai wei
źródło
1
Tylko kod odpowiedzi są naprawdę zniechęcone. Aby pomóc przyszłym czytelnikom, wyjaśnij, co robisz!
itsmysterybox
i następnym razem odniesienie do poprzedniej odpowiedzi stackoverflow.com/a/53056170/1084764 zamiast po prostu kopiować wklejanie
Raykud
0

Tylko \ " my stuff\" działało dla mnie. I mam w sobie różne dziwne postacie my stuff.

Sevastyan Savanyuk
źródło