462 Stimmen

Ist es möglich, in Gradle eine Variable zu deklarieren, die in Java verwendbar ist?

Ist es möglich, eine Variable in Gradle zu deklarieren, die in Java verwendet werden kann? Ich möchte im Grunde einige Variablen in der build.gradle deklarieren und diese dann zur Build-Zeit (offensichtlich) abrufen. Genau wie Präprozessor-Makros in C/C++...

Ein Beispiel für eine Deklaration könnte so aussehen ... :

android {
    debug {
        A_VAR_RETRIEVABLE_IN_JAVA = 42
    }
    release {
        A_VAR_RETRIEVABLE_IN_JAVA = 42+52
    }
}

Gibt es eine Möglichkeit, so etwas zu tun?

866voto

rciovati Punkte 27123

Hier sind zwei Möglichkeiten, um den Wert von Gradle an Java zu übergeben;

Java-Konstanten generieren

android {
    buildTypes {
        debug {
            buildConfigField "int", "FOO", "42"
            buildConfigField "String", "FOO_STRING", "\"foo\""
            buildConfigField "boolean", "LOG", "true"
        }

        release {
            buildConfigField "int", "FOO", "52"
            buildConfigField "String", "FOO_STRING", "\"bar\""
            buildConfigField "boolean", "LOG", "false"
        }
    }
}

Sie können darauf mit BuildConfig.FOO zugreifen

Android-Ressourcen generieren

android {
    buildTypes {
        debug{
            resValue "string", "app_name", "My App Name Debug"
        }
        release {
            resValue "string", "app_name", "My App Name"
        }
    }
}

Sie können darauf wie gewohnt mit @string/app_name oder R.string.app_name zugreifen

128voto

Denis Punkte 2622

Ein Beispiel für die Verwendung eines Api-App-Schlüssels in einer Android-Anwendung (Java und XML)

gradle.properties

AppKey="XXXX-XXXX"

build.gradle

buildTypes {
//...
    buildTypes.each {
        it.buildConfigField 'String', 'APP_KEY_1', AppKey
        it.resValue 'string', 'APP_KEY_2', AppKey
    }
}

Verwendung im Java-Code

Log.d("UserActivity", "onCreate, APP_KEY: " + getString(R.string.APP_KEY_2));

BuildConfig.APP_KEY_1

Verwendung im XML-Code

33voto

michael Punkte 7677

Beispiel zur Verwendung von Systemeigenschaften, die in build.gradle festgelegt und von der Java-Anwendung gelesen werden (nach der Frage in den Kommentaren):

Grundsätzlich wird im build.gradle die test-Aufgabe mit der systemProperty-Methode der Testaufgabe verwendet, um eine Systemeigenschaft festzulegen, die zur Laufzeit übergeben wird:

apply plugin: 'java'
group = 'beispiel'
version = '0.0.1-SNAPSHOT'

repositories {
    mavenCentral()
    // mavenLocal()
    // maven { url 'http://localhost/nexus/content/groups/public'; }
}

dependencies {
    testCompile 'junit:junit:4.8.2'
    compile 'ch.qos.logback:logback-classic:1.1.2'
}

test {
  logger.info '==test=='
  systemProperty 'MY-VAR1', 'VALUE-TEST'
}

Und hier ist der Rest des Beispielscodes (den Sie wahrscheinlich ableiten könnten, der hier aber trotzdem enthalten ist): Er ruft eine Systemeigenschaft MY-VAR1 ab, die zur Laufzeit auf VALUE-TEST festgelegt werden soll:

package beispiel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  static final Logger log=LoggerFactory.getLogger(HelloWorld.class);
  public static void main(String args[]) {
    log.info("Betrete main...");
    final String val = System.getProperty("MY-VAR1", "UNSET (MAIN)");
    System.out.println("(main.out) Hallo Welt: " + val);
    log.info("(main.log) MY-VAR1=" + val);
  }
}

Testfall: Wenn MY-VAR1 nicht festgelegt ist, sollte der Test fehlschlagen:

package beispiel;
...
public class HelloWorldTest {
    static final Logger log=LoggerFactory.getLogger(HelloWorldTest.class);
    @Test public void testEnv() {
        HelloWorld.main(new String[]{});
        final String val = System.getProperty("MY-VAR1", "UNSET (TEST)");
        System.out.println("(test.out) var1=" + val);
        log.info("(test.log) MY-VAR1=" + val);
        assertEquals("Umgebungsvariable MY-VAR1 gesetzt.", "VALUE-TEST", val);
    }
}

Ausführen (Hinweis: Der Test besteht):

$ gradle cleanTest test
:cleanTest
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test

BUILD SUCCESSFUL

Ich habe festgestellt, dass der knifflige Teil darin besteht, tatsächlich die Ausgabe von Gradle zu erhalten... Daher ist hier das Logging konfiguriert (slf4j+logback), und die Protokolldatei zeigt die Ergebnisse (alternativ können Sie gradle --info cleanTest test ausführen; es gibt auch Eigenschaften, die stdout in die Konsole leiten, aber, Sie wissen schon, warum):

$ cat app.log
INFO Test worker beispiel.HelloWorld - Betrete main...
INFO Test worker beispiel.HelloWorld - (main.log) MY-VAR1=VALUE-TEST
INFO Test worker beispiel.HelloWorldTest - (test.log) MY-VAR1=VALUE-TEST

Wenn Sie "systemProperty..." auskommentieren (übrigens funktioniert dies nur in einer test-Aufgabe), dann:

example.HelloWorldTest > testEnv FAILED
    org.junit.ComparisonFailure in HelloWorldTest.java:14

Zur Vollständigkeit hier die Logback-Konfiguration (src/test/resources/logback-test.xml):

        app.log

            %d %p %t %c - %m%n

Dateien:

  • build.gradle
  • src/main/java/beispiel/HelloWorld.java
  • src/test/java/beispiel/HelloWorldTest.java
  • src/test/resources/logback-test.xml

16voto

Boris Treukhov Punkte 16973

Sie können ein Build-Konfigurationsfeld erstellen, das während des Builds über Systemumgebungsvariablen überschreibbar ist:

Fallback wird beim Entwickeln verwendet, aber Sie können die Variable überschreiben, wenn Sie den Build auf Jenkins oder einem anderen Tool ausführen.

In Ihrer App build.gradle:

buildTypes {
        def serverUrl =  '\"' + (System.getenv("SERVER_URL")?: "http://default.fallback.url.com")+'\"'
        debug{
            buildConfigField "String", "SERVER_URL", serverUrl
        }
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField "String", "SERVER_URL", serverUrl
        }
    } 

Die Variable ist als BuildConfig.SERVER_URL verfügbar.

15voto

s.pike Punkte 389

Rciovatis Antwort ist vollkommen richtig, ich wollte nur noch hinzufügen, dass Sie auch Variablen für jeden Build-Typ innerhalb des Standardkonfigurationsbereichs Ihrer build.gradle-Datei erstellen können. Das würde so aussehen:

android {
    defaultConfig {
        buildConfigField "String", "APP_NAME", "\"APP_NAME\""
    }
}

Dies ermöglicht Ihnen den Zugriff über

BuildConfig.App_NAME

Ich wollte auch darauf hinweisen, falls Sie eine gemeinsame Konfiguration wünschen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X