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?
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
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
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" />
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
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
.
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.
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
}
}
}
}
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\""
}
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.
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.