web-dev-qa-db-fra.com

Est-il possible de déclarer une variable dans Gradle utilisable en Java?

Est-il possible de déclarer une variable dans Gradle utilisable en Java? En gros, j'aimerais déclarer quelques vars dans le fichier build.gradle, puis les obtenir (évidemment) au moment de la construction. Tout comme les macros de pré-processeur en C/C++ ...

Un exemple de déclaration serait quelque chose comme ça ...:

Android {
    debug {
        A_VAR_RETRIEVABLE_IN_Java = 42
    }
    release {
        A_VAR_RETRIEVABLE_IN_Java = 42+52
    }
}

Y at-il un moyen de faire quelque chose comme ça?

361
klefevre

Générer des constantes Java

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"
        }
    }
}

Vous pouvez y accéder avec BuildConfig.FOO

Générer des ressources Android

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

Vous pouvez y accéder de la manière habituelle avec @string/app_name ou R.string.app_name

719
rciovati

Exemple d'utilisation d'une clé d'application Api dans une application Android (Java et 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
    }
}

Utilisation en code Java

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

BuildConfig.APP_KEY_1

Utilisation en code xml

<data Android:scheme="@string/APP_KEY_2" />
82
Denis

Exemple d'utilisation de propriétés système, défini dans build.gradle, lu à partir d'une application Java (suite à la question dans les commentaires):

Fondamentalement, en utilisant la tâche test dans build.gradle, avec la méthode de tâche de test systemProperty, définissant une propriété système transmise au moment de l'exécution:

apply plugin: 'Java'
group = 'example'
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'
}

Et voici le reste de l'exemple de code (que vous pouvez probablement déduire, mais qui est inclus ici de toute façon): il obtient une propriété système MY-VAR1, qui devrait être définie à l'exécution à VALUE-TEST:

package example;
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("entering main...");
    final String val = System.getProperty("MY-VAR1", "UNSET (MAIN)");
    System.out.println("(main.out) hello, world: " + val);
    log.info("main.log) MY-VAR1=" + val);
  }
}

Testcase: si MY-VAR n'est pas défini, le test doit échouer:

package example;
...
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("env MY-VAR1 set.", "VALUE-TEST", val);
    }
}

Run (note: le test passe):

$ 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

J'ai trouvé que la partie la plus délicate consiste à obtenir la sortie de gradle ... Ainsi, la journalisation est configurée ici (slf4j + logback) et le fichier journal affiche les résultats (sinon exécutez gradle --info cleanTest test; certaines propriétés obtiennent stdout à la console, mais vous savez pourquoi):

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

Si vous commentez "systemProperty..." (qui, d'ailleurs, ne fonctionne que dans une tâche test), alors:

example.HelloWorldTest > testEnv FAILED
    org.junit.ComparisonFailure at HelloWorldTest.Java:14

Pour être complet, voici la configuration de la consignation (src/test/resources/logback-test.xml):

<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>app.log</file>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d %p %t %c - %m%n</pattern>
        </layout>
 </appender>
 <root level="info">
     <appender-ref ref="FILE"/>
</root>
</configuration> 

Des dossiers:

  • build.gradle
  • src/main/Java/example/HelloWorld.Java
  • src/test/Java/example/HelloWorldTest.Java
  • src/test/resources/logback-test.xml
27
michael

Vous pouvez créer un champ de configuration de construction pouvant être écrasé via des variables d’environnement système lors de la construction:

Le repli est utilisé lors du développement, mais vous pouvez remplacer la variable lorsque vous exécutez la compilation sur Jenkins ou un autre outil.

Dans votre application 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
        }
    } 

La variable sera disponible sous la forme BuildConfig.SERVER_URL.

12
Boris Treukhov

la réponse de rciovati est tout à fait correcte. Je voulais simplement ajouter un autre point de repère sur lequel vous pouvez également créer des variables pour chaque type de construction dans la partie de configuration par défaut de votre build.gradle. Cela ressemblerait à ceci:

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

Cela vous permettra d’avoir accès à travers

BuildConfig.App_NAME

Je voulais juste noter ce scénario aussi si vous voulez une configuration commune.

3
s.pike

J'utilise ce code et travaille très bien.

def baseUrl = '\"http://patelwala.com/myapi/"'
def googleServerKey = '\"87171841097-opu71rk2ps35ibv96ud57g3ktto6ioio.apps.googleusercontent.com"'
Android {
  buildTypes {
  release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
        buildConfigField 'String', 'BASE_URL', baseUrl
        buildConfigField 'String', 'web_client_id', googleServerKey
    }
    releasedebug {
        initWith debug
        buildConfigField 'String', 'BASE_URL', baseUrl
        buildConfigField 'String', 'web_client_id' ,googleServerKey
    }
    debug {

        buildConfigField 'String', 'BASE_URL', baseUrl
        buildConfigField 'String', 'web_client_id', googleServerKey
    }
 }
}

}

1
Hits sapra

Comment pouvez-vous insérer String result of function dans buildConfigField

Voici un exemple de date de construction dans un ensemble de formats lisibles par l'homme:

def getDate() {
    return new SimpleDateFormat("dd MMMM yyyy", new Locale("ru")).format(new Date())
}

def buildDate = getDate()

defaultConfig {
    buildConfigField "String", "BUILD_DATE", "\"$buildDate\""
}
0
anil

Aucune des réponses ci-dessus ne m’a donné de directives; j’ai donc passé deux heures à apprendre les méthodes de Groovy.

Je voulais pouvoir aller contre une production, un bac à sable et un environnement local. Parce que je suis paresseux, je voulais seulement changer l'URL à un endroit. Voici ce que je suis venu avec:

 flavorDimensions 'environment'
    productFlavors {
        production {
            def SERVER_Host = "evil-company.com"
            buildConfigField 'String', 'API_Host', "\"${SERVER_Host}\""
            buildConfigField 'String', 'API_URL', "\"https://${SERVER_Host}/api/v1/\""
            buildConfigField 'String', 'WEB_URL', "\"https://${SERVER_Host}/\""
            dimension 'environment'
        }
        rickard {
            def LOCAL_Host = "192.168.1.107"
            buildConfigField 'String', 'API_Host', "\"${LOCAL_Host}\""
            buildConfigField 'String', 'API_URL', "\"https://${LOCAL_Host}/api/v1/\""
            buildConfigField 'String', 'WEB_URL', "\"https://${LOCAL_Host}/\""
            applicationIdSuffix ".dev"
        }
    }

Syntaxe alternative, car vous ne pouvez utiliser que ${variable} avec des guillemets doubles dans les méthodes Groovy.

    rickard {
        def LOCAL_Host = "192.168.1.107"
        buildConfigField 'String', 'API_Host', '"' + LOCAL_Host + '"'
        buildConfigField 'String', 'API_URL', '"https://' + LOCAL_Host + '/api/v1/"'
        buildConfigField 'String', 'WEB_URL', '"https://' + LOCAL_Host + '"'
        applicationIdSuffix ".dev"
    }

Ce qui était difficile à comprendre pour moi, c’est que les chaînes doivent être déclarées comme des chaînes entourées de guillemets. En raison de cette restriction, je ne pouvais pas utiliser directement la référence API_Host, ce que je voulais faire en premier lieu.

0
Rickard Elimää

J'utilise

buildTypes.each {
    it.buildConfigField 'String', 'GoogleMapsApiKey', "\"$System.env.GoogleMapsApiKey\""
}

C'est basé sur la réponse de Dennis mais la récupère d'une variable d'environnement.

0
Marc